<< Click to Display Table of Contents >> Интеграция с внешними системами > Запросы к сервису интеграции Создание пакетного запроса |
Если нужно выполнить несколько операций в одном запросе к сервису интеграции, используйте пакетный запрос (Batch Request). В одном пакетном запросе можно:
•создавать сущности с обязательным свойством-коллекцией. Например, добавить в систему многоадресное входящее или исходящее письмо;
•создавать несколько сущностей с обязательным свойством-ссылкой. Например, создать для новых сотрудников записи в справочнике Сотрудники и сразу же создать обязательные связанные записи в справочнике Персоны;
•совершать операции в рамках одной транзакции. Например, создать договор и все дополнительные соглашения к нему;
•массово создавать или обновлять сущности. Например, настроить ежедневную синхронизацию оргструктуры компании, если сотрудники работают одновременно в двух системах.
Пакетный запрос состоит из:
•индивидуальных операций, которыми могут быть GET-, POST-, PATCH- и DELETE-запросы к типам сущностей, а также GET- и POST-запросы к функциям;
•наборов изменений (changeset) – нескольких индивидуальных операций, которые выполняются в отдельной транзакции.
Разработчик составляет из наборов изменений и индивидуальных операций единый запрос. Сервис интеграции выполнит их в указанном порядке и сформирует единый ответ. В нем содержатся ответы на все подзапросы пакетного запроса.
Если индивидуальная операция завершилась с ошибкой, все изменения данных в результате запроса отменятся. А если ошибка возникнет в результате выполнения подзапроса в наборе изменений, отменятся все изменения, произведенные с начала транзакции. После этого сервис интеграции продолжит выполнять подзапросы из пакетного запроса.
Важно. В пакетном запросе нельзя использовать потоковую передачу данных.
Пакетные запросы можно создавать:
•в виде консольного приложения;
Напишите POST-запрос, в котором укажите:
1.URL формата:
{Протокол https или http}://{имя сервера, на котором установлен сервис интеграции}/{имя сервиса интеграции}/odata/$batch
Пример:
https://DirectumRXServer.com/Integration/odata/$batch
2.Обязательный заголовок Content-Type со значением multipart/mixed и с параметром boundary. Значение параметра задает разработчик.
Указанный в заголовке boundary разграничивает начало и конец пакетного запроса. Параметр должен быть уникальным и неизменным в рамках отправляемого запроса.
Пример:
Content-Type: multipart/mixed; boundary=batch_4e5da736-624f-40c4-bc98-da0b2f72393c
3.Содержимое тела запроса. Каждая операция внутри пакетного запроса имеет обязательные заголовки:
•Content-Type со значением application/http;
•Content-Transfer-Encoding со значением binary.
Если в теле запроса используются наборы изменений, то их разграничивают с помощью отдельного параметра boundary. Для каждого набора изменений значение параметра должно быть уникальным и неизменным. Упоминание параметра всегда должно начинаться с --. В конце пакетного запроса добавьте -- и в начало параметра, и в конец. Кроме этого, у каждого подзапроса набора изменений добавьте обязательный заголовок Content-ID с указанием идентификатора. Он требуется, чтобы определить порядок, в котором OData-контроллеры будут исполнять подзапросы в наборе изменений.
Ограничения пакетного HTTP-запроса:
•до 100 индивидуальных операций и наборов изменений в одном запросе;
•до 1000 подзапросов в одном наборе изменений.
Пример
Предположим, пакетным запросом к сервису интеграции необходимо получить запись справочника «Роль» (Sungero.CoreEntities.Roles) с идентификатором 8, а в отдельном наборе изменений создать два простых документа (SimpleDocument).
В запросе используется два параметра boundary: batch_<GUID> для пакетного запроса и changeset_<GUID> для набора изменений. Значения GUID в примере произвольные.
POST /Integration/odata/$batch HTTP/1.1
Host: DirectumRXServer.com
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
Content-Type: multipart/mixed; boundary=batch_4e5da736-624f-40c4-bc98-da0b2f72393c
--batch_4e5da736-624f-40c4-bc98-da0b2f72393c
Content-Type: application/http
Content-Transfer-Encoding: binary
GET https://DirectumRXServer.com/Integration/odata/IRoles(8) HTTP/1.1
--batch_4e5da736-624f-40c4-bc98-da0b2f72393c
Content-Type: multipart/mixed; boundary=changeset_0057179c-3dd0-4c59-b336-813fd39aae3d
--changeset_0057179c-3dd0-4c59-b336-813fd39aae3d
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1
POST https://DirectumRXServer.com/Integration/odata/ISimpleDocuments HTTP/1.1
Content-ID: 1
Prefer: return=minimal
OData-Version: 4.0
Content-Type: application/json; odata.metadata=minimal; odata.streaming=true; IEEE754Compatible=false; charset=utf-8
{
"Name":"Новый простой документ"
}
--changeset_0057179c-3dd0-4c59-b336-813fd39aae3d
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 2
POST https://DirectumRXServer.com/Integration/odata/ISimpleDocuments HTTP/1.1
Content-ID: 2
Prefer: return=minimal
OData-Version: 4.0
Content-Type: application/json; odata.metadata=minimal; odata.streaming=true; IEEE754Compatible=false; charset=utf-8
{
"Name":"Второй новый простой документ"
}
--changeset_0057179c-3dd0-4c59-b336-813fd39aae3d--
--batch_4e5da736-624f-40c4-bc98-da0b2f72393c--
Пакетный запрос в консольном приложении
В среде разработки с установленной библиотекой Simple.OData.Client создайте консольное приложение, в котором:
1.Укажите URL запроса, аутентификационные данные и обязательные заголовки. Подробнее см. раздел «Разработка консольного приложения для интеграции».
2.Создайте экземпляр класса ODataBatch с заданными параметрами.
3.Для каждого запроса создайте переменную, в которую поместите результаты выполнения запроса.
4.Напишите запросы с использованием Basic API или Fluent API. Чтобы в пакетном запросе обращаться к созданным в нем сущностям, используйте отрицательные идентификаторы.
Пример
Необходимо пакетным запросом к сервису интеграции:
•получить запись справочника «Роль» (Sungero.CoreEntities.Roles) с идентификатором 8;
•в наборе изменений создать простой документ (SimpleDocument) и версию для него. Заполнить содержимое документа.
Примечание. Пример кода приведен для ситуации, когда разработка ведется в отдельной локальной системе Directum RX или в тестовом контуре. В этом случае для работы достаточно незашифрованного соединения с помощью протокола HTTP, а для аутентификации в сервисе интеграции используется базовая аутентификация.
/// <summary>
/// URL сервиса интеграции.
/// </summary>
private const string IntegrationServiceUrl = "http://localhost/Integration/odata/";
/// <summary>
/// Логин для Basic-аутентификации.
/// </summary>
private const string Login = "IntegrationUser";
/// <summary>
/// Пароль для Basic-аутентификации.
/// </summary>
private const string Password = "11111";
// Настройки Simple OData Client: добавление ко всем запросам URL сервиса и
// заголовка с данными аутентификации.
var odataClientSettings = new ODataClientSettings(new Uri(IntegrationServiceUrl));
odataClientSettings.BeforeRequest += (HttpRequestMessage message) =>
{
var authenticationHeaderValue = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{Login}:{Password}"));
message.Headers.Add("Authorization", "Basic " + authenticationHeaderValue);
};
// Создание пакетного запроса.
var odataBatchRequest = new ODataBatch(odataClientSettings);
// Создание переменных getRequestResult и postRequestsResult для сохранения
// ответов сервиса интеграции.
object getRequestResult;
object postRequestsResult;
// Получение записи справочника «Роли» с идентификатором 8.
odataBatchRequest += async odataClient => getRequestResult = await odataClient.For("IRoles").Key(8)
.FindEntryAsync();
// Создание документа типа SimpleDocument. В подзапросе ему присваивается
// идентификатор -1. Идентификатор используется для обращения к сущности только
// внутри текущего запроса.
odataBatchRequest += async odataClient => postRequestsResult = await odataClient.For("ISimpleDocuments")
.Set(new { Id = -1, Name = "Пример простого документа" })
.InsertEntryAsync();
// Поиск подходящего приложения-обработчика для документа. Для упрощения считаем,
// что в ответе сервиса интеграции будет список с одним соответствием.
var associatedApplication = await odataClient.For("IAssociatedApplications")
.Filter("Extension eq 'doc'")
.FindEntriesAsync();
var associatedApplicationId = associatedApplication.First()["Id"];
// Создание версии документа для сущности с идентификатором -1, созданной в
// предыдущем подзапросе. В подзапросе создается запись свойства-коллекции с
// идентификатором -2, который используется для обращения к сущности только внутри
// текущего запроса.
odataBatchRequest += async odataClient => await
odataClient.For("ISimpleDocuments").Key(-1)
.NavigateTo("Versions")
.Set(new { Id = -2, Number = 1, AssociatedApplication = new { Id = associatedApplicationId } })
.InsertEntryAsync();
// Добавление закодированной в Base64 строки в свойство Body версии документа. Для
// примера взята строка "111111". В подзапросе строка добавляется в запись
// свойства-коллекции с идентификатором -2, созданную в предыдущем подзапросе.
odataBatchRequest += async odataClient => await odataClient.For("ISimpleDocuments").Key(-1)
.NavigateTo("Versions").Key(-2)
.NavigateTo("Body")
.Set(new { Value = "MTExMTEx" })
.InsertEntryAsync();
// Выполнение пакетного запроса.
await odataBatchRequest.ExecuteAsync();
Пакетный запрос в формате JSON
Напишите POST-запрос, в котором укажите:
1.URL формата:
{Протокол https или http}://{имя сервера, на котором установлен сервис интеграции}/{имя сервиса интеграции}/odata/$batch
Пример:
https://DirectumRXServer.com/Integration/odata/$batch
2.Обязательный заголовок Content-Type со значением application/json.
3.Содержимое тела запроса. Все операции перечисляются в параметре requests. Для каждой заполните параметры:
•method – метод операции. Возможные значения: GET, POST, PATCH, DELETE;
•atomicityGroup – параметр, в котором указан набор изменений, к которому относится операция. Не нужно указывать, если операция индивидуальная;
•id – идентификатор операции. Определяет порядок выполнения операций в пакетном запросе;
•url – URL операции;
•headers – заголовки операции;
•body – тело операции.
Подробнее о пакетных запросах в формате JSON см. официальную документацию Microsoft, статья JSON Batching.
Пример
Пакетным запросом к сервису интеграции:
•получить запись справочника «Роль» (Sungero.CoreEntities.Roles) с идентификатором 8;
•в наборе изменений создать простой документ (SimpleDocument) и новую версию для него. В версию внести значение.
POST /Integration/odata/$batch HTTP/1.1
Host: DirectumRXServer.com
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
Content-Type: application/json
Accept: application/json
{
{
"requests": [
{
"method": "GET",
"id": "i1",
"url": "IRoles(9)",
"headers": {
"content-type": "application/json",
"odata-version": "4.0"
}
},
{
"method": "POST",
"atomicityGroup": "g1",
"id": "g1-r1",
"url": "ISimpleDocuments",
"headers": {
"content-type": "application/json; odata.metadata=minimal; odata.streaming=true",
"odata-version": "4.0"
},
"body": { "Id": -1, "Name": "Простой документ" }
},
{
"method": "POST",
"atomicityGroup": "g1",
"id": "g1-r2",
"url": "ISimpleDocuments(-1)/Versions",
"headers": {
"content-type": "application/json; odata.metadata=minimal; odata.streaming=true",
"odata-version": "4.0"
},
"body": { "Id" : -2, "Number" : 1, "AssociatedApplication" : {"Id" : 10 } }
},
{
"method": "PATCH",
"atomicityGroup": "g1",
"id": "g1-r3",
"url": "ISimpleDocuments(-1)/Versions(-2)/Body",
"headers": {
"content-type": "application/json; odata.metadata=minimal; odata.streaming=true",
"odata-version": "4.0"
},
"body": { "Value" : "MTExMTEx" }
}
]
}
}
© Компания Directum, 2024 |