Создание пользовательского конфигурационного сервиса
Glossary Item Box
Общие положения
Сервисная модель Creatio реализует базовый набор веб-сервисов, с помощью которых может быть организована интеграция Creatio с внешними приложениями и системами. Примерами системных сервисов являются EntityDataService.svc, который предоставляет возможности обмена данными с Creatio по протоколу OData, а также ProcessEngineService.svc, с помощью которого можно осуществлять запуск бизнес-процессов Creatio из внешних приложений. Эти сервисы реализованы на основе технологии WCF и управляются на уровне IIS.
Также в Creatio существуют конфигурационные веб-сервисы, предназначенные для вызова из клиентской части приложения. С помощью конфигурационных веб-сервисов можно реализовывать специфические интеграционные задачи.
Конфигурационный веб-сервис представляет собой RESTful-сервис, реализованный на базе технологии WCF. Он доступен по следующему адресу:
[Адрес приложения]/0/rest/[Название пользовательского сервиса]/[Конечная точка пользовательского сервиса]?[Опциональные параметры]
Например:
http://mysite.сreatio.com/0/rest/UsrCustomConfigurationService/GetContactIdByName?Name=User1
ВАЖНО
Пользовательский конфигурационный сервис доступен только после аутентификации пользователя с помощью сервиса AuthService.svc (см. "Сервис аутентификации AuthService.svc").
Начиная с версии 7.14.1 изменен подход к написанию веб-сервисов. Класс сервиса должен быть наследником Terrasoft.Web.Common.BaseService.
В Terrasoft.Web.Common.BaseService уже определены свойства UserConnection и AppConnection, благодаря которым отпадает необходимость получать эти объекты из HttpContext.Current, а также свойство HttpContextAccessor, которое предоставляет доступ к контексту.
HttpContextAccessor обеспечивает унифицированный доступ к HttpContext в обоих фреймворках - и в ASP.NET Framework и ASP.Net Core. Реализована возможность получать контекст двумя способами:
- Не рекомендуемый способ: Через статическое свойство HttpContext.Current. Для обеспечения легкой миграции от фреймворка ASP.NET Framework к ASP.Net Core нужно добавить в исходный код сервиса с помощью директивы using пространство имен Terrasoft.Web.Http.Abstractions, в котором реализован унифицированный доступ к HttpContext, используя статическое свойство HttpContext.Current. При адаптации старого кода к новому фреймворку достаточно заменить namespace System.Web на Terrasoft.Web.Http.Abstractions.
- Рекомендуемый способ: Через IHttpContextAccessor зарегистрированный в DI (ClassFactory). Позволяет покрывать код тестами.
ВАЖНО
Использовать в конфигурации конкретную реализацию доступа к контексту из ASP.NET (библиотека System.Web) или ASP.NET Core (библиотека Microsoft.AspNetCore.Http) запрещено.
Пример использования свойств родительского класса Terrasoft.Web.Common.BaseService.
namespace Terrasoft.Configuration.UsrCustomNamespace { using Terrasoft.Web.Common; [ServiceContract] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] public class UsrCustomConfigurationService: BaseService { // Метод сервиса. [OperationContract] [WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)] public void SomeMethod() { ... var currentUser = UserConnection.CurrentUser; // UserConnection - свойство BaseService. var sdkHelpUrl = AppConnection.SdkHelpUrl; // AppConnection - свойство BaseService. var httpContext = HttpContextAccessor.GetInstance(); // HttpContextAccessor - свойство BaseService. ... } } }
Пример адаптации сервиса к ASP.Net Core
namespace Terrasoft.Configuration.UsrCustomNamespace { using Terrasoft.Web.Http.Abstractions; // Использовать вместо System.Web [ServiceContract] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] public class UsrCustomConfigurationService { // Метод сервиса. [OperationContract] [WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)] public void SomeMethod() { ... var httpContext = HttpContext.Current; ... } } }
Чтобы создать пользовательский веб-сервис в конфигурации:
- В пакете разработки создайте схему типа [Исходный код].
- В исходном коде схемы создайте класс сервиса. Задействуйте пространство имен в Terrasoft.Configuration или любое вложенное в него пространство имен. Пометьте класс атрибутами [ServiceContract] и [AspNetCompatibilityRequirements] с необходимыми параметрами. Класс сервиса должен быть наследником Terrasoft.Web.Common.BaseService.
- Добавьте в класс реализацию методов, соответствующую конечным точкам сервиса. Каждый метод сервиса должен быть помечен атрибутами [OperationContract] и [WebInvoke] с требуемыми параметрами. При необходимости передавать данные сложных типов (экземпляры объектов, коллекции, массивы и т. п.) вы можете реализовать дополнительные классы, экземпляры которых будет принимать или возвращать метод вашего сервиса. Каждый такой класс должен быть помечен атрибутом [DataContract], а поля класса — атрибутом [DataMember].
- Выполните публикацию схемы исходного кода.
После публикации схемы созданный веб-сервис станет доступен для вызова из программного кода конфигурационных схем, а также из внешних приложений (см. "Вызов конфигурационного сервиса с помощью ServiceHelper").
Описание примера
Создать пользовательский конфигурационный сервис, возвращающий идентификатор контакта по предоставленному имени. Если найденных контактов несколько, то необходимо возвратить идентификатор только первого найденного контакта. Если контакт не найден, сервис должен вернуть пустую строку.
Исходный код
Пакет с реализацией примера можно скачать по ссылке.
Алгоритм реализации примера
1. Создать схему [Исходный код]
В разделе [Конфигурация] на вкладке [Схемы] выполните действие [Добавить] — [Исходный код] ([Add] — [Source code]) (рис. 1).
Рис. 1. — Добавление схемы [Исходный код] ([Source Code])
Установите для схемы следующие свойства:
- Название ([Name]) — UsrCustomConfigurationService.
- Заголовок ([Title]) — UsrCustomConfigurationService.
2. Создать класс сервиса
На вкладке [Исходный код] (Source code) добавьте:
- Пространство имен, вложенное в Terrasoft.Configuration. Название может быть любым, например, UsrCustomConfigurationService.
- Пространства имен, типы данных которых будут задействованы в вашем классе. Для этого используется директива using. Полный перечень пространств имен приведен в исходном коде ниже.
- Класс, например, UsrCustomConfigurationService, унаследованный от Terrasoft.Nui.ServiceModel.WebService.BaseService. Пометьте класс атрибутами [ServiceContract] и [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)].
Пример исходного кода с объявлением класса приведен ниже.
3. Реализовать методы, соответствующие конечным точкам сервиса
Для реализации конечной точки возврата идентификатора контакта по его имени, добавьте в класс метод public string GetContactIdByName(string Name). Параметр Name должен принимать имя контакта. После обращения к базе данных с помощью EntitySchemaQuery, метод возвратит приведенный к строке идентификатор первого найденного контакта или значение "" (пустую строку).
Полностью исходный код с реализацией класса сервиса:
namespace Terrasoft.Configuration.UsrCustomNamespace { using System; using System.ServiceModel; using System.ServiceModel.Web; using System.ServiceModel.Activation; using Terrasoft.Core; using Terrasoft.Web.Common; using Terrasoft.Core.Entities; [ServiceContract] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] public class UsrCustomConfigurationService: BaseService { // Метод, возвращающий идентификатор контакта по его имени. [OperationContract] [WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)] public string GetContactIdByName(string Name) { // Результат по умолчанию. var result = ""; // Экземпляр EntitySchemaQuery, обращающийся в таблицу Contact базы данных. var esq = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "Contact"); // Добавление колонок в запрос. var colId = esq.AddColumn("Id"); var colName = esq.AddColumn("Name"); // Фильтрация данных запроса. var esqFilter = esq.CreateFilterWithParameters(FilterComparisonType.Equal, "Name", Name); esq.Filters.Add(esqFilter); // Получение результата запроса. var entities = esq.GetEntityCollection(UserConnection); // Если данные получены. if (entities.Count > 0) { // Возвратить значение колонки "Id" первой записи результата запроса. result = entities[0].GetColumnValue(colId.Name).ToString(); // Также можно использовать такой вариант: // result = entities[0].GetTypedColumnValue<string>(colId.Name); } // Возвратить результат. return result; } } }
После внесения изменений сохраните и опубликуйте схему.
В результате выполнения примера в Creatio станет доступен новый конфигурационный сервис UsrCustomConfigurationService. При обращении к конечной точке GetContactIdByName этого сервиса, например, из браузера, будет возвращен идентификатор контакта (рис. 2) или значение "" (рис. 3).
К СВЕДЕНИЮ
Обратите внимание на формат результата вызова. В ответе о сервиса передается объект, содержащий свойство, название которого составлено из имени вызываемого метода и суффикса “Result”. Значение свойства объекта содержит возвращенное сервисом значение идентификатора контакта или пустую строку.
Рис. 2. — Результат выполнения запроса. Идентификатор контакта найден.
Рис. 3. — Результат выполнения запроса. Идентификатор контакта не найден.
ВАЖНО
При обращении к сервису без предварительного входа в приложение возникнет ошибка отсутствия авторизации (рис. 4).
Рис. 4. — Результат выполнения запроса. Нет авторизации.