DataService. Создание записи. Пример
Glossary Item Box
Общие положения
Веб-служба DataService приложения bpm'online является RESTful-сервисом, т.е. поддерживает передачу состояния представления (Representational State Transfer, REST). В общем случае REST является очень простым интерфейсом управления информацией без использования каких-то дополнительных внутренних прослоек, т.е. данные не нужно преобразовывать в какой-либо сторонний формат, например, XML. В простом RESTful-сервисе каждая единица информации однозначно определяется глобальным идентификатором, таким как URL. Каждый URL, в свою очередь, имеет строго заданный формат. Однако это не всегда удобно для передачи больших массивов данных.
В DataService данные автоматичеcки могут быть сконфигурированы в различные форматы данных, такие как XML, JSON, HTML, CSV и JSV. Структура данных определяется так называемыми контрактами данных. Полный перечень контрактов данных, используемых службой DataService, изложен в статье "Веб-служба DataService".
Контракт данных InsertQuery
Для добавления записей в раздел используется контракт данных InsertQuery. Передача непосредственно данных в службу DataService осуществляется по HTTP протоколу при помощи POST-запроса по следующему URL:
// Формат URL для POST-запроса на добавление данных к DataService. http(s)://[Адрес приложения bpm'online]/[Номер конфигурации]/dataservice/[Формат данных]/reply/InsertQuery // Пример URL для POST-запроса на добавление данных к DataService. http(s)://example.bpmonline.com/0/dataservice/json/reply/InsertQuery
Контракт данных InsertQuery имеет иерархическую структуру с несколькими уровнями вложенности. В серверной части ядра приложения bpm'online он представлен классом InsertQuery пространства имен Terrasoft.Nui.ServiceModel.DataContract библиотеки классов Terrasoft.Nui.ServiceModel.dll. Однако для простоты восприятия иерархическую структуру контракта данных InsertQuery удобно представить в формате объекта JSON:
{ "RootSchemaName":"[Имя корневой схемы объекта]", "OperationType":[Тип операции с записью], "ColumnValues":{ "Items":{ "Имя добавляемой колонки":{ "ExpressionType":[Тип выражения], "Parameter":{ "DataValueType":[Тип данных], "Value":"[Значение колонки]" } }... } } }
Основные свойства класса InsertQuery и их возможные значения представлены в таблице 1.
Табл. 1. — Свойства класса InsertQuery
Свойство | Описание | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
RootSchemaName | Строка, содержащая название корневой схемы объекта добавляемой записи. | ||||||||||
OperationType |
Тип операции с записью. Задается значением перечисления QueryOperationType пространства имен Terrasoft.Nui.ServiceModel.DataContract. Для InsertQuery устанавливается значение QueryOperationType.Insert. Значения перечисления QueryOperationType:
|
||||||||||
ColumnValues | Содержит коллекцию значений колонок добавляемой записи. Имеет тип ColumnValues, определенный в пространстве имен Terrasoft.Nui.ServiceModel.DataContract. |
Класс ColumnValues имеет единственное свойство Items, которое определено как коллекция ключей и значений Dictionary<string, ColumnExpression>. Ключом является строка с названием добавляемой колонки, а значением — объект типа ColumnExpression, определенный в пространстве имен Terrasoft.Nui.ServiceModel.DataContract. Основные свойства класса ColumnExpression, используемые при добавлении записей, приведены в табл. 2.
Табл. 2. — Основные свойства класса ColumnExpression
Свойство | Описание | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
ExpressionType |
Тип выражения, определяющий значение, которое будет содержаться в добавляемой колонке. Задается значением перечисления EntitySchemaQueryExpressionType пространства имен Terrasoft.Core.Entities, определенного в библиотеке классов Terrasoft.Core. Для InsertQuery устанавливается значение EntitySchemaQueryExpressionType.Parameter. Значения перечисления EntitySchemaQueryExpressionType:
|
||||||||||
Parameter |
Определяет значение, которое будет содержаться в добавляемой колонке. Имеет тип Parameter, определенный в пространстве имен Terrasoft.Nui.ServiceModel.DataContract. |
Класс Parameter имеет несколько свойств, из которых только два используются для добавления записи (табл.3).
Табл. 3. — Основные свойства класса Parameter
Свойство | Описание | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
DataValueType |
Тип данных значения, которое будет содержаться в добавляемой колонке. Задается значением перечисления DataValueType пространства имен Terrasoft.Nui.ServiceModel.DataContract Значения перечисления DataValueType:
|
||||||||||||||||||||||||||||||||
Value |
Объект, содержащий значение добавляемой колонки. Имеет тип Object. |
Пример создания записи в стороннем приложении
Описание кейса
Необходимо создать консольное приложение, которое, используя службу DataService, добавит в раздел [Контакт] запись со следующими данными:
- ФИО — Иванов Иван Иванович;
- Должность — Разработчик;
- Рабочий телефон — +12 345 678 00 00.
Пример реализации
Полностью исходный код выполнения данного примера можно посмотреть в репозитории GitHub здесь.
Алгоритм реализации кейса
1. Создать и настроить проект консольного приложения C#
Используя среду разработки Microsoft Visual Studio (версии не ниже 2017), необходимо создать проект консольного приложения Visual C#, указав в качестве названия проекта, например, DataServiceInsertExample. Свойству проекта [Target framework] необходимо установить значение .NET Framework 4.7.
В секцию References проекта нужно добавить зависимости от следующих библиотек:
- System.Web.Extensions.dll — библиотека классов, входящая в .NET Farmework;
- Terrasoft.Core.dll — библиотека основных классов серверного ядра приложения. Можно найти по следующему пути: [Каталог с установленным приложением]\Terrasoft.WebApp\bin\Terrasoft.Core.dll;
- Terrasoft.Nui.ServiceModel.dll — библиотека классов служб приложения. Можно найти по следующему пути: [Каталог с установленным приложением]\Terrasoft.WebApp\bin\Terrasoft.Nui.ServiceModel.dll.
В файл исходного кода приложения необходимо добавить директивы using:
using System; using System.Text; using System.IO; using System.Net; using System.Collections.Generic; using Terrasoft.Nui.ServiceModel.DataContract; using Terrasoft.Core.Entities; using System.Web.Script.Serialization;
2. В исходный код приложения добавить объявления полей и констант
Для доступа к возможностям службы DataService в исходный код приложения необходимо добавить следующие поля и константы:
// Основной URL приложения bpm'online. Необходимо заменить на пользовательский. private const string baseUri = @"http://example.bpmonline.com"; // Строка запроса к методу Login сервиса AuthService.svc. private const string authServiceUri = baseUri + @"/ServiceModel/AuthService.svc/Login"; // Строка пути запроса InsertQuery. private const string insertQueryUri = baseUri + @"/0/DataService/json/reply/InsertQuery"; // Cookie аутентификации bpm'online. private static CookieContainer AuthCookie = new CookieContainer();
Здесь объявлены три строковых константных поля, с помощью которых формируются пути выполнения запросов на аутентификацию и запросов на добавление данных. Данные об аутентификации будут сохранены в поле AuthCookie.
3. Добавить метод, выполняющий аутентификацию в приложении bpm'online
Для доступа создаваемого приложения к веб-службе DataService необходимо выполнить аутентификацию.
Алгоритм действия и пример реализации метода, который выполняет запрос к службе AuthService.svc для аутентификации пользователя, подробно изложены в статье Аутентификация внешних запросов к веб-сервисам bpm'online.
4. Добавить непосредственную реализацию запроса на добавление записи
Поскольку объявленная ранее константа insertQueryUri содержит путь для отправки данных в формате JSON, то отправляемые данные нужно предварительно сконфигурировать в виде строки, содержащей описание JSON-объекта, соответствующего контракту данных InsertQuery. Это можно сделать непосредственно в некоторой строчной переменной, однако намного удобнее и безопаснее с точки зрения возможности возникновения ошибок создать экземпляр класса InsertQuery, заполнить его свойства, а затем сериализовать его в строку. Сделать это можно, добавив следующий исходный код:
// Экземпляр класса запроса. var insertQuery = new InsertQuery() { // Название корневой схемы. RootSchemaName = "Contact", // Коллекция добавляемых значений колонок. ColumnValues = new ColumnValues() }; // Экземпляр класса выражения запроса к схеме объекта. // Предназначен для конфигурирования колонки [ФИО]. var columnExpressionName = new ColumnExpression { // Тип выражения запроса к схеме объекта — параметр. ExpressionType = EntitySchemaQueryExpressionType.Parameter, // Параметр выражения запроса. Parameter = new Parameter { // Значение параметра. Value = "Иванов Иван Иванович", // Тип данных параметра — строка. DataValueType = DataValueType.Text } }; // Экземпляр класса выражения запроса к схеме объекта. // Предназначен для конфигурирования колонки [Рабочий телефон]. var columnExpressionPhone = new ColumnExpression { ExpressionType = EntitySchemaQueryExpressionType.Parameter, Parameter = new Parameter { Value = "+12 345 678 00 00", DataValueType = DataValueType.Text } }; // Экземпляр класса выражения запроса к схеме объекта. // Предназначен для конфигурирования колонки [Должность]. var columnExpressionJob = new ColumnExpression { ExpressionType = EntitySchemaQueryExpressionType.Parameter, Parameter = new Parameter { // GUID записи "Разработчик" системного справочника [Должность]. // Необходимо заменить на GUID записи в приложении bpm'online пользователя. Value = "11D68189-CED6-DF11-9B2A-001D60E938C6", // Тип данных параметра — уникальный идентификатор. DataValueType = DataValueType.Guid } }; // Инициализация коллекции колонок запроса. insertQuery.ColumnValues.Items = new Dictionary<string, ColumnExpression>(); // Добавление выражений запроса в коллекцию добавляемых колонок. // Колонка [ФИО]. insertQuery.ColumnValues.Items.Add("Name", columnExpressionName); // Колонка [Рабочий телефон]. insertQuery.ColumnValues.Items.Add("Phone", columnExpressionPhone); // Колонка [Должность]. insertQuery.ColumnValues.Items.Add("Job", columnExpressionJob); // Сериализация экземпляра класса запроса на добавление в JSON-строку. var json = new JavaScriptSerializer().Serialize(insertQuery);
ПРИМЕЧАНИЕ В данном примере для сокращения объема статьи уникальный идентификатор записи "Разработчик" системного справочника [Должность] задан строчным литералом. Определить его можно, например, используя запрос SelectQuery c фильтром по названию должности. |
На завершающем шаге необходимо выполнить POST-запрос к службе DataService. Для этого необходимо создать экземпляр класса HttpWebRequest, заполнить его свойства, присоединить к запросу созданную ранее строку с JSON-объектом, а затем выполнить и обработать результат запроса к службе DataService. Для этого нужно добавить следующий исходный код:
// Преобразование строки JSON-объекта в массив байтов. byte[] jsonArray = Encoding.UTF8.GetBytes(json); // Создание экземпляра HTTP-запроса. var insertRequest = HttpWebRequest.Create(insertQueryUri) as HttpWebRequest; // Определение метода запроса. insertRequest.Method = "POST"; // Определение типа содержимого запроса. insertRequest.ContentType = "application/json"; // Добавление полученных ранее аутентификационных cookie в запрос на получение данных. insertRequest.CookieContainer = AuthCookie; // Установить длину содержимого запроса. insertRequest.ContentLength = jsonArray.Length; // Добавление CSRF токена в заголовок запроса. CookieCollection cookieCollection = AuthCookie.GetCookies(new Uri(authServiceUri)); string csrfToken = cookieCollection["BPMCSRF"].Value; insertRequest.Headers.Add("BPMCSRF", csrfToken); // Помещение в содержимое запроса JSON-объекта. using (var requestStream = insertRequest.GetRequestStream()) { requestStream.Write(jsonArray, 0, jsonArray.Length); } // Выполнение HTTP-запроса и получение ответа от сервера. using (var response = (HttpWebResponse)insertRequest.GetResponse()) { // Вывод ответа в консоль. using (StreamReader reader = new StreamReader(response.GetResponseStream())) { Console.WriteLine(reader.ReadToEnd()); } }
Полностью исходный код выполнения данного примера можно посмотреть в репозитории GitHub здесь.
Пример создания записи в приложении bpm'online
Описание кейса
Добавить в раздел [Контакт] кнопку при нажатии на которую вызывается метод, который, используя класс InsertQuery, добавляет запись со следующими данными:
- ФИО — Иванов Иван Иванович;
- Должность — Разработчик;
- Рабочий телефон — +12 345 678 00 00.
Пример реализации
Полностью исходный код выполнения данного примера можно скачать здесь.
Алгоритм реализации кейса
1. Добавить в раздел [Контакты] кнопку
Процесс добавления кнопки в раздел подробно описан в статье "Добавление кнопки в раздел".
Для рассматриваемого кейса необходимо создать замещающий клиентский модуль раздела [Контакты] (рис. 1).
Рис. 1. — Свойства замещающего клиентского модуля
В созданной клиентской схеме добавить локализуемую строку InsertQueryContactButtonCaption, для которой установить значение "Добавить контакт" (рис. 2).
Рис. 2. — Свойства локализуемой строки
В массив diff добавить конфигурационный объект с настройками расположения кнопки на странице.
diff: /**SCHEMA_DIFF*/[ // Метаданные для добавления в раздел пользовательской кнопки. { // Выполняется операция добавления элемента на страницу. "operation": "insert", // Название родительского элемента управления, в который добавляется кнопка. "parentName": "ActionButtonsContainer", // Кнопка добавляется в коллекцию элементов управления // родительского элемента (мета-имя которого указано в parentName). "propertyName": "items", // Мета-имя добавляемой кнопки. "name": "InsertQueryContactButton", // Дополнительные свойства элемента. "values": { // Тип добавляемого элемента — кнопка. itemType: Terrasoft.ViewItemType.BUTTON, // Привязка заголовка кнопки к локализуемой строке схемы. caption: { bindTo: "Resources.Strings.InsertQueryContactButtonCaption" }, // Привязка метода-обработчика нажатия кнопки. click: { bindTo: "onInsertQueryContactClick" }, "layout": { "column": 1, "row": 6, "colSpan": 1 } } } ]/**SCHEMA_DIFF*/
2. Добавить метод-обработчик события нажатия кнопки
Для того чтобы при нажатии на созданную в разделе кнопку добавлялась запись с необходимыми данными, в секцию methods замещающей клиентской схемы необходимо добавить следующий метод:
methods: { // Метод-обработчик нажатия кнопки. onInsertQueryContactClick: function() { // Создание экземпляра класса Terrasoft.InsertQuery. var insert = Ext.create("Terrasoft.InsertQuery", { // Название корневой схемы. rootSchemaName: "Contact" }); // Установка значений-параметров Terrasoft.ParameterExpression. // Создается экземпляр значения-параметра и добавляется в коллекцию значений колонок. // Создание экземпляра значения-параметра для колонки [ФИО]. insert.setParameterValue("Name", "Иванов Иван Иванович", Terrasoft.DataValueType.TEXT); // Создание экземпляра значения-параметра для колонки [Рабочий телефон]. insert.setParameterValue("Phone", "+12 345 678 00 00", Terrasoft.DataValueType.TEXT); // Создание экземпляра значения-параметра для колонки [Должность]. insert.setParameterValue("Job", "11D68189-CED6-DF11-9B2A-001D60E938C6", Terrasoft.DataValueType.GUID); // Запрос к серверу на обновление данных insert.execute(function(response) { // Вывод ответа от сервера в консоль браузера. window.console.log(response); }); // Обновление данных реестра. this.reloadGridData(); } }
К СВЕДЕНИЮ В отличие от предыдущего примера, авторизация не требуеся, поскольку программный код выполняется непосредственно в приложении bpm'online. |
Реализация класса InsertQuery для клиентской части ядра приложения несколько отличается от реализации класса InsertQuery в его серверной части. Так, для создания параметров предусмотрен метод setParameterValue, а для выполнения запроса — метод execute. Узнать обо всех доступных свойствах и методах класса InsertQuery, реализованного в клиентской части ядра приложения, можно в документации по API здесь.
Полностью исходный код выполнения данного примера можно скачать здесь.