Документация по разработке bpm’online
PDF

Работа с объектами bpm'online по протоколу OData с использованием Http-запросов

Glossary Item Box

В данной статье будут рассмотрены следующие вопросы: 

Для успешной компиляции приведенных ниже примеров в программный код необходимо добавить:

  • директивы Using
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Xml;
using System.Xml.Linq; 
  • объявление переменных и констант
// Строка адреса BPMonline сервиса OData.
private const string serverUri = "http://<имя_сервера>/<имя_приложения_BPMonline>/0/ServiceModel/EntityDataService.svc/";
private const string authServiceUtri = "http://<имя_сервера>/<имя_приложения_BPMonline>/ServiceModel/AuthService.svc/Login";

// Ссылки на пространства имен XML.
private static readonly XNamespace ds = "http://schemas.microsoft.com/ado/2007/08/dataservices";
private static readonly XNamespace dsmd = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata";
private static readonly XNamespace atom = "http://www.w3.org/2005/Atom"; 

Операции работы с объектами и коллекциями объектов

Получение коллекции объектов

Для получения коллекции объектов используется HTTP-метод GET.

Записи возвращаются постранично, по 40 записей на страницу. Если предполагается, что запрос вернет больше 40 записей, необходимо обеспечить получение следующей страницы по достижении конца текущей.

В примере ниже демонстрируется использование конструкции $select для получения отдельных полей объекта. В результате выполнения запроса в примере будет возвращена коллекция контактов с полями Id и Name.

В приведенном примере также используется Forms-аутентификация. Имя и пароль пользователя bpm'online передаются в параметрах метода GetOdataCollectionByAuthByHttpExample(string userName, string userPassword).

// Строка запроса
// GET <Адрес приложения BPMonline>/0/ServiceModel/EntityDataService.svc/ContactCollection?$select=Id,Name 

public static void GetOdataCollectionByAuthByHttpExample(string userName, string userPassword)
{
    // Создание запроса на аутентификацию.
    var authRequest = HttpWebRequest.Create(authServiceUtri) as HttpWebRequest;
    authRequest.Method = "POST";
    authRequest.ContentType = "application/json";
    var bpmCookieContainer = new CookieContainer();
    // Включение использования cookie в запросе.
    authRequest.CookieContainer = bpmCookieContainer;
    // Получение потока, ассоциированного с запросом на аутентификацию.
    using (var requestStream = authRequest.GetRequestStream())
    {
        // Запись в поток запроса учетных данных пользователя BPMonline и дополнительных параметров запроса.
        using (var writer = new StreamWriter(requestStream))
        {
            writer.Write(@"{
                                ""UserName"":""" + userName + @""",
                                ""UserPassword"":""" + userPassword + @""",
                                ""SolutionName"":""TSBpm"",
                                ""TimeZoneOffset"":-120,
                                ""Language"":""Ru-ru""
                                }");
        }
    }
    // Получение ответа от сервера. Если аутентификация проходит успешно, в объекте bpmCookieContainer будут 
    // помещены cookie, которые могут быть использованы для последующих запросов.
    using (var response = (HttpWebResponse)authRequest.GetResponse())
    {
        // Создание запроса на получение данных от сервиса OData.
        var dataRequest = HttpWebRequest.Create(serverUri + "ContactCollection?$select=Id, Name")
                                as HttpWebRequest;
        // Для получения данных используется HTTP-метод GET.
        dataRequest.Method = "GET";
        // Добавление полученных ранее аутентификационных cookie в запрос на получение данных.
        dataRequest.CookieContainer = bpmCookieContainer;
        // Получение ответа от сервера.
        using (var dataResponse = (HttpWebResponse)dataRequest.GetResponse())
        {
            // Загрузка ответа сервера в xml-документ для дальнейшей обработки.
            XDocument xmlDoc = XDocument.Load(dataResponse.GetResponseStream());
            // Получение коллекции объектов контактов, соответствующих условию запроса.
            var contacts = from entry in xmlDoc.Descendants(atom + "entry")
                           select new
                               {
                                   Id = new Guid(entry.Element(atom + "content")
                                                      .Element(dsmd + "properties")
                                                      .Element(ds + "Id").Value),
                                   Name = entry.Element(atom + "content")
                                               .Element(dsmd + "properties")
                                               .Element(ds + "Name").Value
                               };
            foreach (var contact in contacts)
            {
                // Выполнение действий с контактами.
            }
        }
    } 

К СВЕДЕНИЮ

Если необходимо отправлять запрос и получать ответ в формате JSON, укажите в заголовке запроса:

Content-Type = "application/json"

Accept = "application/json;odata=verbose"

Если необходимо, чтобы запрос возвращал более, чем 40 записей за один раз, это можно реализовать с использованием параметра $top, в котором указывается требуемое количество возвращаемых запросом записей. Так, в приведенном ниже примере формируется строка запроса к сервису для получения первых 60 объектов коллекции контактов.

Пример использования параметра $top

string requestUri = serverUri + "ContactCollection?$top=60";

В bpm'online поддерживается использование параметра $skip, который позволяет запрашивать у сервиса ресурсы, пропустив заданное количество записей.

В приведенном ниже примере продемонстрировано формирование строки запроса к сервису для получения коллекции контактов, начиная с 11 записи.

Пример использования параметра $skip

string requestUri = serverUri + "ContactCollection?$skip=10";

Ресурсы сервиса можно получать в отсотрированном виде. Для этого в запросе нужно использовать параметр $orderby [asc|desc], в котором указать, по какому полю выполнять сортировку результатов. Кроме того, для данного параметра можно указать одно из направлений сортировки:

  • по возрастанию (asc)
  • по убыванию (desc)

По умолчанию используется сортировка по возрастанию (asc).

В примере ниже формируется строка запроса к сервису для получения коллекции контактов, отсортированной по возрастанию значения поля Name.

Пример использования параметра $orderby для сортировки по возрастанию

string requestUri = serverUri + "ContactCollection?$orderby=Name";

Параметры $top, $skip, $orderby можно использовать в различных комбинациях для получения конкретного фрагмента коллекции.

Пример использования параметров $orderby, $top, $skip в комбинации

string requestUri = serverUri + "ContactCollection?$top=4&$skip=1&$orderby=City/Name";

Получение объекта с заданными характеристиками

Для получения объекта используется HTTP-метод GET.

Получение конкретного объекта, который отвечает определенным условиям (например, контакт с заданным Id или контрагент с определенным названием и т.д.) можно реализовать несколькими способами (в приведенных ниже примерах используется Basic-аутентификация запросов).

Задание Id искомого объекта в качестве параметра коллекции

// Строка запроса:
// GET <Адрес приложения BPMonline>/0/ServiceModel/EntityDataService.svc/ContactCollection(guid'00000000-0000-0000-0000-000000000000')

public static void GetOdataObjectByIdExample()
{
    // Id искомого объекта.
    string contactId = "00000000-0000-0000-0000-000000000000";

    // Формирование строки запроса к сервису.
    string requestUri = serverUri + "ContactCollection(guid'" + contactId + "')";

    // Создание объекта запроса к сервису.
    var request = HttpWebRequest.Create(requestUri) as HttpWebRequest;
    request.Method = "GET";
    request.Credentials = new NetworkCredential("BPMUserName", "BPMUserPassword");
    using (var response = request.GetResponse())
    {
        // Получение ответа от сервиса в xml-формате.
        XDocument xmlDoc = XDocument.Load(response.GetResponseStream());
        // Получение коллекции объектов контактов, соответствующих условию запроса.
        var contacts = from entry in xmlDoc.Descendants(atom + "entry")
                       select new
                           {
                               Id = new Guid(entry.Element(atom + "content")
                                                 .Element(dsmd + "properties")
                                                 .Element(ds + "Id").Value),
                               Name = entry.Element(atom + "content")
                                           .Element(dsmd + "properties")
                                           .Element(ds + "Name").Value
                               // Инициализация свойств объекта, необходимых для дальнейшего использования.
                           };
        foreach (var contact in contacts)
        {
            // Выполнение действий над контактом.
        }
    }
} 

 

Данный способ можно использовать только в том случае, если необходимо получить объект с заданным идентификатором.

Если в качестве параметров искомого объекта выступает не идентификатор объекта или искомый объект определяется несколькими параметрами, то необходимо использовать конструктцию $filter для определения параметров.

Использование конструкции $filter для формирования сложного условия выбора объекта

Конструкция $filter позволяет строить логические выражения условий выбора искомого объекта.

В выражениях $filter можно использовать ссылки на свойства и литералы, а также строки, числа и логические выражения (true, false). Выражения $filter поддерживают арифметические, логические операции, а также операции группировки, операции со строками, датой и временем. Полный перечень операций конструкции $filter приведен в спецификации OData

Рассмотрим пример получения объекта с заданным Id, используя для задания условия конструкции $filter.

// Строка запроса:
// GET <Адрес приложения BPMonline>/0/ServiceModel/EntityDataService.svc/ContactCollection?$filter=Id eq guid'00000000-0000-0000-0000-000000000000'

public static void GetOdataObjectByFilterConditionExample()
{
    // Id искомого объекта.
    string contactId = "00000000-0000-0000-0000-000000000000";
    // Формирование строки запроса к сервису.
    string requestUri = serverUri + "ContactCollection?$filter = Id eq guid'" + contactId + "'";
    // Создание объекта запроса к сервису.
    var request = HttpWebRequest.Create(requestUri) as HttpWebRequest;
    request.Method = "GET";
    request.Credentials = new NetworkCredential("BPMUserName", "BPMUserPassword");
    using (var response = request.GetResponse())
    {
        // Получение ответа от сервиса в xml-формате.
        XDocument xmlDoc = XDocument.Load(response.GetResponseStream());
        // Получение коллекции объектов контактов, соответствующих условию запроса.
        var contacts = from entry in xmlDoc.Descendants(atom + "entry")
                       select new
                       {
                           Id = new Guid(entry.Element(atom + "content")
                                             .Element(dsmd + "properties")
                                             .Element(ds + "Id").Value),
                           Name = entry.Element(atom + "content")
                                       .Element(dsmd + "properties")
                                       .Element(ds + "Name").Value
                           // Инициализация свойств объекта, необходимых для дальнейшего использования.
                       };
        foreach (var contact in contacts)
        {
           // Выполнение действий над контактом.
        }
    }
} 

С помощью конструкции $filter можно создавать сложные условия по нескольким полям объекта.

Ниже приведен пример возвращения коллекции объектов контактов, которые были созданы пользователем SomeUserName после 1.11.2012

// Строка запроса:
// GET <Адрес приложения BPMonline>/0/ServiceModel/EntityDataService.svc/ContactCollection?$filter=CreatedOn gt datetime'2012-11-01' and CreatedBy/Name eq 'SomeUserName'

public static void GetOdataObjectByFilterDiffConditionExample()
{
    // Имя пользователя, который создал объекты.
    string userName = "BPMUserName";
    // Дата создания объектов.
    string datetime = "2012-11-01";
    // Формирование строки запроса к сервису.
    string requestUri = serverUri + "ContactCollection?$filter=CreatedOn gt datetime'" + datetime +
                                    "'and CreatedBy/Name eq '" + userName + "'";
    // Создание объекта запроса к сервису.
    var request = HttpWebRequest.Create(requestUri) as HttpWebRequest;
    request.Method = "GET";
    request.Credentials = new NetworkCredential(userName, "BPMUserPassword");
    using (var response = request.GetResponse())
    {
        // Получение ответа от сервиса в xml-формате.
        XDocument xmlDoc = XDocument.Load(response.GetResponseStream());
        // Получение коллекции объектов контактов, соответствующих условию запроса.
        var contacts = from entry in xmlDoc.Descendants(atom + "entry")
                       select new
                       {
                           Id = new Guid(entry.Element(atom + "content")
                                             .Element(dsmd + "properties")
                                             .Element(ds + "Id").Value),
                           Name = entry.Element(atom + "content")
                                       .Element(dsmd + "properties")
                                       .Element(ds + "Name").Value
                           // Инициализация свойств объекта, необходимых для дальнейшего использования.
                       };
        foreach (var contact in contacts)
        {
            // Выполнение действий над контактом.
        }
    }
} 

Больше примеров построения запросов с помощью конструкции $filter вы можете найти в статье "Примеры запросов на выборку с фильтрацией".

Создание нового объекта

Для создания объекта используется HTTP-метод POST.

При этом необходимо сформировать тело запроса в формате Atom/XML или JSON таким образом, чтобы он содержал все необходимые поля объекта. Все возможные поля создаваемого объекта описаны в метаданных сервиса.

К СВЕДЕНИЮ

Если необходимо отправлять запрос и получать ответ в формате JSON, укажите в заголовке запроса:

Content-Type = "application/json"

Accept = "application/json;odata=verbose"

Ниже приведен пример создания нового контакта. В примере применяется Basic-аутентификация запроса.

// Строка запроса:
// POST <Адрес приложения BPMonline>/0/ServiceModel/EntityDataService.svc/ContactCollection/

public static void CreateBpmEntityByOdataHttpExample()
{
    // Создание сообщения xml, содержащего данные о создаваемом объекте.
    var content = new XElement(dsmd + "properties",
                  new XElement(ds + "Name", "Иван Иванов"),
                  new XElement(ds + "Dear", "Иван"));
    var entry = new XElement(atom + "entry",
                new XElement(atom + "content",
                new XAttribute("type", "application/xml"), content));
    Console.WriteLine(entry.ToString());
    // Создание запроса к сервису, который будет добавлять новый объект в коллекцию контактов.
    var request = (HttpWebRequest)HttpWebRequest.Create(serverUri + "ContactCollection/");
    request.Credentials = new NetworkCredential("BPMUserName", "BPMUserPassword");
    request.Method = "POST";
    request.Accept = "application/atom+xml";
    request.ContentType = "application/atom+xml;type=entry";
    // Запись xml-сообщения в поток запроса.
    using (var writer = XmlWriter.Create(request.GetRequestStream()))
    {
        entry.WriteTo(writer);
    }
    // Получение ответа от сервиса о результате выполнения операции.
    using (WebResponse response = request.GetResponse())
    {
        if (((HttpWebResponse)response).StatusCode == HttpStatusCode.Created)
        {
            // Обработка результата выполнения операции.
        }
    }
} 

Изменение существующего объекта

Для изменения записи используется HTTP-метод PUT (или MERGE в более новых версиях OData).

К СВЕДЕНИЮ

Если необходимо отправлять запрос и получать ответ в формате JSON, укажите в заголовке запроса:

Content-Type = "application/json"

Accept = "application/json;odata=verbose"

В теле запроса передаются новые значения полей, которые нужно изменить. В строке запроса необходимо указать коллекцию, объект которой изменяется, а в качестве параметра коллекции указать идентификатор изменяемого объекта.

Ниже приведен пример изменения имени контакта с идентификатором 00000000-0000-0000-0000-000000000000 из коллекции контактов ContactCollection. В примере используется Basic-аутентификация запросов.

// Строка запроса:
// PUT <Адрес приложения BPMonline>/0/ServiceModel/EntityDataService.svc/ContactCollection(guid'00000000-0000-0000-0000-000000000000')
// или
// MERGE <Адрес приложения BPMonline>/0/ServiceModel/EntityDataService.svc/ContactCollection(guid'00000000-0000-0000-0000-000000000000')


public static void UpdateExistingBpmEnyityByOdataHttpExample()
{
    // Id записи объекта, который необходимо изменить.
    string contactId = "00000000-0000-0000-0000-000000000000";
    // Создание сообщения xml, содержащего данные об изменяемом объекте.
    var content = new XElement(dsmd + "properties",
            new XElement(ds + "Name", "Новое имя")
    );
    var entry = new XElement(atom + "entry",
            new XElement(atom + "content",
                    new XAttribute("type", "application/xml"),
                    content)
            );
    // Создание запроса к сервису, который будет изменять данные объекта.
    var request = (HttpWebRequest)HttpWebRequest.Create(serverUri
            + "ContactCollection(guid'" + contactId + "')");
    request.Credentials = new NetworkCredential("BPMUserName", "BPMUserPassword");
    // или request.Method = "MERGE";
    request.Method = "PUT";
    request.Accept = "application/atom+xml";
    request.ContentType = "application/atom+xml;type=entry";
    // Запись сообщения xml в поток запроса.
    using (var writer = XmlWriter.Create(request.GetRequestStream()))
    {
        entry.WriteTo(writer);
    }
    // Получение ответа от сервиса о результате выполнения операции.
    using (WebResponse response = request.GetResponse())
    {
        // Обработка результата выполнения операции.
    }
} 

Удаление объекта

Для удаления записи используется HTTP-метод DELETE.

К СВЕДЕНИЮ

Если необходимо отправлять запрос и получать ответ в формате JSON, укажите в заголовке запроса:

Content-Type = "application/json"

Accept = "application/json;odata=verbose"

В строке запроса необходимо указать коллекцию, объект которой удаляется, а в качестве параметра коллекции указать идентификатор удаляемого объекта.

Ниже приведен пример удаления контакта с идентификатором 00000000-0000-0000-0000-000000000000 из коллекции контактов ContactCollection. В примере используется Basic-аутентификация запросов.

// Строка запроса:
// DELETE <Адрес приложения BPMonline>/0/ServiceModel/EntityDataService.svc/ContactCollection(guid'00000000-0000-0000-0000-000000000000')

public static void DeleteBpmEntityByOdataHttpExample()
{
    // Id записи объекта, который необходимо удалить.
    string contactId = "00000000-0000-0000-0000-000000000000";
    // Создание запроса к сервису, который будет удалять данные.
    var request = (HttpWebRequest)HttpWebRequest.Create(serverUri
            + "ContactCollection(guid'" + contactId + "')");
    request.Credentials = new NetworkCredential("BPMUserName", "BPMUserPassword");
    request.Method = "DELETE";
    // Получение ответа от сервися о результате выполненя операции.
    using (WebResponse response = request.GetResponse())
    {
        // Обработка результата выполнения операции.
    }
} 

Функции работы со строками

BPMonine поддерживает следующие функции работы со строками протокола OData, которые могут быть применены для построения выражений конструкции $filter.

Функция Пример строки запроса Результат выполнения запроса
bool substringof(string po, string p) <Адрес сервиса>/ContactCollection?$filter=substringof('Smith', Name) Коллекция контактов, в имени которых присутствует подстрока 'Smith'
string toupper(string p0) <Адрес сервиса>/ContactCollection?$filter=toupper(Name) eq 'TEST USER' Коллекция контактов, имя которых в верхнем регистре равно 'TEST USER'
bool endswith(string p0, string p1) <Адрес сервиса>/ContactCollection?$filter=endswith(Name, 'User') Коллекция контактов, имя которых оканчивается подстрокой 'User'.
int length(string p0) <Адрес сервиса>/ContactCollection?$filter=length(Name) gt 10 Коллекция контактов, длина имени которых больше 10 символов.
string trim(string p0) <Адрес сервиса>/ContactCollection?$filter=trim(Name) eq 'Test User' Коллекция контактов, имя которых после удаления начальных и конечных пробелов равно 'Test User'.

Полный перечень функций работы со строками протокола OData приведен в официальной спецификации OData.

Функции работы с датой и временем

BPMonine поддерживает следующие функции работы с датами протокола OData, которые могут быть применены для построения выражений конструкции $filter.

Функция Пример строки запроса Результат выполнения запроса
int year(DateTime p0) <Адрес сервиса>/ContactCollection?$filter=year(BirthDate) ge 1950 and year(BirthDate) le 1990 Коллекция контактов, чей год рождения находится в интервале от 1950 до 1990 гг. включительно.
int month(DateTime p0) <Адрес сервиса>/ContactCollection?$filter=month(BirthDate) eq 5 Коллекция контактов, родившихся в мае месяце.
int day(DateTime p0) < span>/ContactCollection?$filter=day(BirthDate) eq 15 Коллекция контактов, родившихся 15 числа.
Полный перечень функций работы с датами протокола OData приведен в официальной спецификации OData.

Смотрите также

© Terrasoft 2002-2019.

Был ли данный материал полезен?

Как можно улучшить эту статью?