logo

[ELMA3] Внешний WebAPI

В системе существует набор корневых сервисов, которые служат для взаимодействия с сервером на уровне SDK. Основные возможности, которые предоставляют сервисы: авторизация, получение метаданных системы, чтение данных сущностей, отслеживание изменений сущностей на сервере.

Дополнительно к корневым сервисам на сервере доступно большое количество функциональных сервисов. Эти сервисы предоставляют функционал модулей системы: исполнение задач, создание поручений и событий в календаре и т.д.

Для всех сервисов установлено корневое пространство имен http://bpm-demo.elma-bpm.ru/API/Help.

Корневые сервисы системы

К корневым сервисам относятся:

  1. Сервис авторизацииAuthorizationService.
  2. Сервис чтения данных сущностей – EntityService.
  3. Сервис чтения заголовков сущностей – EntityHeadService.
  4. Сервис отслеживания изменений сущностейEntityChangesService.
  5. Сервис отправки и получения файлов – FilesService.
  6. Сервис получения метаданных системы – MetadataService.

Для всех корневых сервисов предусмотрено две точки входа: WCF HTTP и WCF SOAP. Получить доступ к той или иной точке можно следующим образом:

  1. Для WCF SOAP адрес формируется из имени сервиса без постфикса Service, для AuthorizationService это будет ~/API/Authorization (например, http://bpm-demo.elma-bpm.ru/API/Authorization).
  2. Для WCF HTTP адрес формируется аналогично SOAP, но в качестве корневого адреса нужно использовать ~/API/REST , для AuthorizationService это будет~/API/REST/Authorization (например, http://bpm-demo.elma-bpm.ru/API/REST/Authorization).
  3. Также для WCF HTTP формируется стандартная справка формата .NET WCF, она доступна по адресу ~/API/REST/<Имя сервиса>/Help , для AuthorizationService это будет ~/API/REST/Authorization/Help (например, http://bpm-demo.elma-bpm.ru/API/REST/Authorization/help).

В режиме WCF HTTP все сервисы (кроме MetadataService) поддерживают как XML, так и JSON форматы данных. Формат устанавливается при помощи заголовка:

  1. Accept: application/xml (или Content-Type: application/xml для POST запроса) – для обмена в формате XML.
  2. Accept: application/json (или Content-Type: application/json для POST запроса) – для обмена в формате JSON.
Замечание
Сервис MetadataService поддерживает только XML формат обмена данными

Авторизация запросов

Для поддержки безопасности в системе используется авторизация запросов. Механизм авторизации следующий:

  1. Вы используете сервис авторизации AuthorizationService:
    1. Метод LoginWithBasic авторизует по протоколу basic;
    2. Метод LoginWithUserName авторизует по логину\паролю.
  2. В ответе вам приходит токен авторизации AuthToken (строковое представление структуры System.Guid):
    1. Данный токен авторизации необходимо в дальнейшем передавать как заголовок (Header) вместе с каждым запросом к методам (для WCF HTTP используйте просто заголовки HTTP: AuthToken: ... ). Если метод требует авторизации, в сгенерированной справке это будет явно указано. Следует обратить внимание на то, что время жизни токена AuthToken составляет 15 минут;
    2. Дополнительно в ответе приходит Токен сессии SessionToken (см. ниже), идентификатор текущего пользователя CurrentUserId, и его текущая культура Lang.

Доверенные приложения и сессии соединения

Добавлены токены доверенных внешних приложений ApplicationToken и токены "сессии" SessionToken . Токен внешнего приложения нужен для идентификации доверенного приложения ( ELMA for IPad, ElmaAgent, Outlook и др.), у этого токена есть срок истечения. При первой авторизации нужно обязательно передавать в заголовке токен приложения: ApplicationToken: ...

Токен приложения можно настроить и посмотреть в разделе Администрирование – Система – Внешние приложения.

Настройки токенов внешних приложений осуществляются в разделе Администрирование, при этом есть ряд системных токенов, срок истечения которых устанавливается отдельно для каждого приложения.

Токен сессии – на самом деле "сессия" здесь обозначает уникальную пару "Приложение + Пользователь", токен сессии нужен как раз для идентификации этой пары на сервере. Дополнительно при первой авторизации (по логину паролю), если в приложении для этого пользователя уже есть "Токен сессии", то нужно его передавать также в заголовке: SessionToken: .... . Это необходимо для обеспечения отслеживания изменений на сервере в связке с клиентом.

Создание нового внешнего приложения и токена

Создадим внешнее приложение и токен для него. Для этого нужно перейти в раздел Администрирование – Система – Внешние приложения и нажать на кнопку Добавить.

Рис. 1. Раздел "Администрирование Система Внешние приложения". Кнопка "Добавить"

Далее заполняем необходимые поля для нашего приложения и нажимаем Сохранить.

Рис. 2. Форма создания нового внешнего приложения

После этого нужно перейти в созданное приложение и включить его.

Рис. 3. Карточка внешнего приложения. Кнопка "Включить"

Теперь можно добавить токен. Переходим во вкладку Токены приложения, нажимаем на Добавить токен и выбираем срок истечения.

Рис. 4. Карточка внешнего приложения. Вкладка "Токены приложения"

Новое внешние приложение готово, и теперь можно с ним работать.

Справка по WebAPI

Существует автогенерируемая справка по WebAPI. В ней содержится информация о том, какие есть доступные сервисы, объекты, перечисления и типы данных для свойств. Она расположена по относительной ссылке ~/API/Help (например http://bpm-demo.elma-bpm.ru/API/Help). В этой справке можно найти описание всех доступных сервисов (как корневых, так и функциональных) и их методов.

Рис. 5. Справка по публичным веб-службам ELMA. Главная страница

Рассмотрим более подробно каждый из этих пунктов.

Список доступных публичных веб-сервисов

Содержит информацию о том, какие веб-сервисы системы доступны для вызова сторонним приложениям.

Рис. 6. Справка по публичным веб-службам ELMA. Список доступных сервисов системы

Каждый из веб-сервисов содержит информацию о методах, которые можно вызвать из данного веб-сервиса, а также о параметрах метода и возвращаемом значении.

Рис. 7. Страница веб-сервиса

Также каждый сервис содержит информацию о способах вызова методов: либо через WSDL, либо через HTTP-запросы.

Информация о вызове через WSDL

Рис. 8. Информация о вызове через WSDL

Информация о вызове через HTTP-запросы

Рис. 9. Информация о вызове через HTTP-запросы

Перейдя внутрь метода, можно узнать информацию о том, в каком формате необходимо создавать запрос и в каком виде придет ответ.

Рис. 10. Страница метода запроса

Список типов объектов (сущностей)

Содержит информацию обо всех объектах системы, в том числе и о процессах.

Рис. 11. Справка по публичным веб-службам ELMA. Список типов объектов (сущностей)

Рис. 12. Справка по публичным веб-службам ELMA. Список процессов

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

Рис. 13. Страница типа объекта (сущности)

Список перечислений

Содержит информацию обо всех доступных перечислениях системы.

Рис. 14. Справка по публичным веб-службам ELMA. Список доступных перечислений

Каждое представленное здесь перечисление хранит информацию о своих значениях.

Рис. 15. Страница перечисления

Список типов данных для свойств

Содержит информацию об идентификаторах типа данных. Здесь:

1. Идентификатор типа данных – это уникальный идентификатор категории объекта. Для стандартных .Net объектов он всегда разный. Для объектов системы ELMA может повторяться. Ниже приведён список основных категорий и их идентификаторов:

  • Сущность (72ed98ca-f260-4671-9bcd-ff1d80235f47);
  • Тип проекта (d1397b84-f5ab-4665-984f-fdeb8f77eb0b);
  • Тип документа (a3a41ae4-30e2-4c46-bba2-ee55efdc7b90);
  • Тип РКК (691ed407-4007-4530-834b-0c6a34bb9af1);
  • Перечисление (849c1ac9-4d46-4194-8cbb-43f84adf9c17).

2. Идентификатор подтипа данных – это уникальный идентификатор каждого типа объекта. Данный идентификатор не может повторятся.

Рис. 16. Справка по публичным веб-службам ELMA. Список типов данных

Пример использования WebAPI

Есть два варианта взаимодействия с WebAPI кодом: через WSDL-сервисы и через HTTP-запросы. Ниже представлены примеры минимальной работы с WebAPI для каждого варианта.

Работа через HTTP-запросы

Для примера будет работать в консольном приложении. Для создания консольного приложения откройте VisualStudioNew project (новый проект) – VisualC# – ConsoleApplication (консольное приложение) – Create (Создать).

Для работы необходимо подключить пространства имен System.Net, System.IO и EleWise.ELMA.SDK.

В первую очередь нужно получить токен авторизации. Для этого пишем следующий код:

        //создаем токен приложения
        public static string ApplicationToken = "FCD9913007A3A1483D55700EAC702C41A42B3CE4F887538ADC37FACBC397160F57612B2DBC8E839A61C6A05D24508177C48EFE4D3898931C46F4C91B52F133E3";

            //создаем веб запрос
            HttpWebRequest req = WebRequest.Create(String.Format("http://localhost:2016/API/REST/Authorization/LoginWith?username=admin")) as HttpWebRequest;
            req.Headers.Add("ApplicationToken", ApplicationToken);
            req.Method = "POST";
            req.Timeout = 10000;
            req.ContentType = "application/json; charset=utf-8";

            //данные для отправки. используется для передачи пароля. пароль нужно записать вместо пустой строки
            var sentData = Encoding.UTF8.GetBytes("");
            req.ContentLength = sentData.Length;
            Stream sendStream = req.GetRequestStream();
            sendStream.Write(sentData, 0, sentData.Length);

            //получение ответа
            var res = req.GetResponse() as HttpWebResponse;
            var resStream = res.GetResponseStream();
            var sr = new StreamReader(resStream, Encoding.UTF8);

            //достаем необходимые данные
            var dict = new JsonSerializer().Deserialize(sr.ReadToEnd(), typeof(Dictionary<string, string>)) as Dictionary<string, string>;
            var authToken = dict["AuthToken"];	
            var sessionToken = dict["SessionToken"]; 
Внимание!

Так как идет работа с потоком, после использования функции ReadToEnd() символов в переменной sr не будет (останется только пустая строка). Результатом выполнения функции будет вот такой ответ:

{
"AuthToken":"39c45713-59c0-48db-aeee-77e93579b330",
"CurrentUserId":"1",
"Lang":"ru-RU",
"SessionToken":"0B56F7016540A75C5352942FDD3E40FAC7E73663B3BD1279B39780215603285F28432FD2D2940842A5BFF83BA97830A07577004F6CE61E10E2A9C1885A74192B"

}

Здесь:

  1. AuthToken – токен авторизации (то, что нужно получить для дальнейшей работы).
  2. CurrentUserId – идентификатор текущего авторизированного пользователя.
  3. Lang – текущая локаль пользователя.
  4. SessionToken – токен сессии (также необходим для того, чтобы сессии не плодились на сервере, передается вместе с AuthToken).

Токен авторизации получен, теперь можно его использовать. Для примера можно загрузить задачу. Для этого используйте следующий код:

        public static void LoadTask(string authToken, string sessionToken)
        {
            var typeUid = "f532ef81-20e1-467d-89a4-940c57a609bc";
            var entityId = "37";  
                     
            HttpWebRequest taskReq = WebRequest.Create(String.Format("http://localhost:2016/API/REST/Entity/Load?type={0}&id={1}", typeUid, entityId)) as HttpWebRequest;
            taskReq.Method = "GET";            
            taskReq.Headers.Add("AuthToken", authToken);
            taskReq.Headers.Add("SessionToken", sessionToken);
            taskReq.Timeout = 10000;
            taskReq.ContentType = "application/json; charset=utf-8";

            var res = taskReq.GetResponse() as HttpWebResponse;
            var resStream = res.GetResponseStream();
            var sr = new StreamReader(resStream, Encoding.UTF8);

            var myTask = sr.ReadLine();
            Console.WriteLine(myTask);
            Console.ReadKey();
        }

где

  • typeUid – уникальный идентификатор типа Задача;
  • entityId – идентификатор объекта.

Результат выполнения:

{"Items":
[
{
"Data":null,
"DataArray":[],
"Name":"Id",
"Value":"37"
},
{
"Data":null,
"DataArray":[],
"Name":"TypeUid",
"Value":"f532ef81-20e1-467d-89a4-940c57a609bc"
},
{
"Data":null,
"DataArray":[],
"Name":"Uid",
"Value":"e44c7deb-9f9c-4cc5-8034-90906e13149a"
},
{
"Data":null,
"DataArray":[],
"Name":"Subject",
"Value":"Задача для тестирования веб сервиса"
}
],
"Value":null}

Здесь представлена лишь часть ответа, так как весь ответ слишком большой. Если вам нужна только часть полей какого-либо объекта, используйте функцию LoadTree. Чтобы загрузить несколько объектов одним запросом, используйте функцию Query (для загрузки всех полей объекта) или QueryTree (для загрузки определённых полей объекта).

Ниже приведен код вызова функции Query.

        public static void LoadTaskList(string authToken, string sessionToken)
        {
            var typeUid = "f532ef81-20e1-467d-89a4-940c57a609bc";
            var eqlQuery = "";
            var limit = "15";
            var offset = "0";
            var sort = "";
            var filterProviderUid = "";
            var filterProviderData = "";
            var filter = "";
            HttpWebRequest queryReq = WebRequest.Create(String.Format(@"http://localhost:2016/API/REST/Entity/Query?type={0}&q={1}&limit={2}&offset={3}&sort={4}&filterProviderUid={5}&filterProviderData={6}&filter={7}",
            typeUid, eqlQuery, limit, offset, sort, filterProviderUid, filterProviderData, filter)) as HttpWebRequest;
            queryReq.Method = "GET";
            queryReq.Headers.Add("AuthToken", authToken);
            queryReq.Headers.Add("SessionToken", sessionToken);
            queryReq.Timeout = 10000;
            queryReq.ContentType = "application/json; charset=utf-8";

            var res = queryReq.GetResponse() as HttpWebResponse;
            var resStream = res.GetResponseStream();
            var sr = new StreamReader(resStream, Encoding.UTF8);

            var queryResult = sr.ReadLine();
            Console.WriteLine(queryResult);
            Console.ReadKey();
        }

где

  • typeUid – уникальный идентификатор типа Задача;
  • eqlQuery – запрос на языке EQL;
  • limit – количество получаемых элементов;
  • offset – начальный элемент;
  • sort – сортировка по указанному свойству объекта;
  • filterProviderUid – уникальный идентификатор провайдера фильтрации;
  • filterProviderData – данные для провайдера фильтрации;
  • filter – значения полей для фильтра сущности.

Сортировка по указанному свойству объекта может происходить по возрастанию и по убыванию. Например:

  • CreationDate – сортировка по возрастанию по свойству CreationDate;
  • CreationDate DESC – сортировка по убыванию по свойству CreationDate.

Так как формат запроса GET и параметры не могут располагаться через пробел, то необходимо либо использовать формат CreationDate%20DESC или использовать Uri.EscapeUriString перед string.Format.

Переходим к работе с объектом. Завершим задачу, которую загрузили с помощью функции Load. Также при завершении задачи передадим комментарий.

public static void ExecuteTask(string authToken, string sessionToken)
        {
            HttpWebRequest taskReq = WebRequest.Create("http://localhost:2016/API/REST/Tasks/Complete") as HttpWebRequest;
            taskReq.Method = "POST";
            taskReq.Headers.Add("AuthToken", authToken);
            taskReq.Headers.Add("SessionToken", sessionToken);
            taskReq.Timeout = 10000;
            taskReq.ContentType = "application/json; charset=utf-8";            

            var request = @"
{
	""Items"":
	   [
		   {
				""Data"":null,
				""DataArray"":[],
				""Name"":""TaskId"",
				""Value"":""1""
			},
			{
				""Data"":
					{
						""Items"":
						[
							{
								""Data"":null,
								""DataArray"":[],
								""Name"":""Text"",
								""Value"":""Text for comment""
							}
						],
						""Value"":null
					},
				""DataArray"":[],
				""Name"":""Comment"",
				""Value"":null
			},
		],
	""Value"":null
}";

            var sentData = Encoding.UTF8.GetBytes(request);
            taskReq.ContentLength = sentData.Length;
            Stream sendStream = taskReq.GetRequestStream();
            sendStream.Write(sentData, 0, sentData.Length);

            var res = taskReq.GetResponse() as HttpWebResponse;
            var resStream = res.GetResponseStream();
            var sr = new StreamReader(resStream, Encoding.UTF8);
            Console.WriteLine(sr.ReadToEnd());
            Console.ReadKey();
        }

Обратите внимание на передаваемую в метод информацию. Это минимальная структура для завершения задачи с комментарием.

Результат выполнения:

{
"Items":
[
{
"Data":null,
"DataArray":[],
"Name":"TypeUid",
"Value":"e1859f3d-c62f-11c5-828b-3b38521cab82"
},
{
"Data":null,
"DataArray":[],
"Name":"Result",
"Value":"True"
}
],
"Value":null
}

В поле Result вернулось значение True. Это значит, что задача была успешно завершена. Если по какой-либо причине этого не удалось сделать, в поле Result вернется значение False.

Может возникнуть ситуация, когда ваш токен авторизации стал недействителен. Такая ситуация возникает, например, если сервер перезапустили, а данные об авторизации у вас в приложении старые. Чтобы проверить, действует ли еще ваш токен авторизации, используйте функцию CheckToken в AuthorizationService.

        public static void LoadTask(string authToken, string sessionToken)
        {
            var typeUid = "f532ef81-20e1-467d-89a4-940c57a609bc";
            var entityId = "1";

            
            HttpWebRequest checkTokenReq = WebRequest.Create(String.Format("http://localhost:2016/API/REST/Authorization/CheckToken?token={0}", authToken)) as HttpWebRequest;
            checkTokenReq.Method = "GET";
            checkTokenReq.Timeout = 10000;
            checkTokenReq.ContentType = "application/json; charset=utf-8";
            try
            {
                //если ошибки нет, то забираем токены сессии и авторизации из полученного ответа
                var res1 = checkTokenReq.GetResponse() as HttpWebResponse;
                var resStream1 = res1.GetResponseStream();
                var sr1 = new StreamReader(resStream1, Encoding.UTF8);
                var result = sr1.ReadToEnd();
                Console.WriteLine(result);
                Console.ReadKey();

                var dict = new JsonSerializer().Deserialize(result, typeof(Dictionary<string, string>)) as Dictionary<string, string>;
                authToken = dict["AuthToken"];
                sessionToken = dict["SessionToken"];
            }
            catch (Exception)
            {
                //если при выполнении запроса произошла ошибка, заново запускаем запрос авторизации
                HttpWebRequest req = WebRequest.Create(String.Format("http://localhost:2016/API/REST/Authorization/LoginWith?username=admin")) as HttpWebRequest;
                req.Headers.Add("ApplicationToken", ApplicationToken);
                req.Headers.Add("SessionToken", sessionToken);
                req.Method = "POST";
                req.Timeout = 10000;
                req.ContentType = "application/json; charset=utf-8";

                var sentData = Encoding.UTF8.GetBytes("");
                req.ContentLength = sentData.Length;
                Stream sendStream = req.GetRequestStream();
                sendStream.Write(sentData, 0, sentData.Length);

                //получение ответа
                var res1 = req.GetResponse() as HttpWebResponse;
                var resStream1 = res1.GetResponseStream();
                var sr1 = new StreamReader(resStream1, Encoding.UTF8);
                var result = sr1.ReadToEnd();

                var dict = new JsonSerializer().Deserialize(result, typeof(Dictionary<string, string>)) as Dictionary<string, string>;
                authToken = dict["AuthToken"];
                sessionToken = dict["SessionToken"];
            }

            HttpWebRequest taskReq = WebRequest.Create(String.Format("http://localhost:2016/API/REST/Entity/Load?type={0}&id={1}", typeUid, entityId)) as HttpWebRequest;
            taskReq.Method = "GET";            
            taskReq.Headers.Add("AuthToken", authToken);
            taskReq.Headers.Add("SessionToken", sessionToken);
            taskReq.Timeout = 10000;
            taskReq.ContentType = "application/json; charset=utf-8";

            var res = taskReq.GetResponse() as HttpWebResponse;
            var resStream = res.GetResponseStream();
            var sr = new StreamReader(resStream, Encoding.UTF8);

            var myTask = sr.ReadLine();
            Console.WriteLine(myTask);
            Console.ReadKey();
        }

Работа через WSDL

Сделаем все те же действия, только используя WSDL-сервисы. Чтобы их использовать, нужно добавить их в проект. Для добавления в проект нажмите правой кнопкой мыши на Refernces AddServiceReference, в поле Адрес введите нужную ссылку и нажмитена кнопку Перейти. В случае успешного перехода нажмите на кнопку ОК.

Рис. 17. Диалоговое окно добавления ссылки на службу

При успешном добавлении сервис появится в Обозревателе решений.

Рис. 18. Обозреватель решений

Аналогичным образом добавляем ссылку на IEntityService.

Здесь нам понадобится пространство имен System.ServiceModel.Web.

Приступаем к работе. Для удобства создадим класс WsdlService и начнем в нем работу.

    public class WsdlService
    {
        private ChannelFactory<EntityService.IEntityServiceChannel> _entityServiceFactory;
        private ChannelFactory<AuthorizationService.IAuthorizationServiceChannel> _authServiceFactory;

        public void TestStart()
        {
            _entityServiceFactory =
                new ChannelFactory<EntityService.IEntityServiceChannel>(
                    new BasicHttpBinding() {MaxReceivedMessageSize = Int32.MaxValue}, "http://localhost:2016/API/Entity");
            _authServiceFactory =
                new ChannelFactory<AuthorizationService.IAuthorizationServiceChannel>(new BasicHttpBinding(),
                    "http://localhost:2016/API/Authorization");
            GetAuthToken();
        }

        private string sessionToken;
        private Guid authToken;

        public void GetAuthToken()
        {

            var authorizationService = _authServiceFactory.CreateChannel();

            using (new OperationContextScope((IContextChannel) authorizationService))
            {
                WebOperationContext.Current.OutgoingRequest.Headers.Add("ApplicationToken",
                    "FCD9913007A3A1483D55700EAC702C41A42B3CE4F887538ADC37FACBC397160F57612B2DBC8E839A61C6A05D24508177C48EFE4D3898931C46F4C91B52F133E3");
                var token = authorizationService.LoginWithUserName("admin", "");
                authToken = token.AuthToken;
                sessionToken = token.SessionToken;
            }
        }
    }

Переменная _entityServiceFactory (и подобные) служит для создания канала связи с сервером. Они инициализируются в функции TestStart(). Сам же канал связи создается с помощью CreateChannel().

Рассмотрим функцию GetAuthToken(). Переменная authorizationService – это уже созданный сервис, внутри себя содержит методы, которые описаны в справке по WebAPI.

Использование канала происходит внутри using( … ) { … }. Это нужно для передачи необходимых заголовков при использовании различных функций сервиса.

Здесь в заголовки передается токен приложения. Далее используем функцию LoginWithUserName, и при её успешном выполнении получаем токен авторизации в виде System.Guid и токен сессии в виде строки.

Чтобы проверить, действителен ли ваш токен авторизации, используйте функцию CheckToken.

    		using (new OperationContextScope((IContextChannel)authService))
                {
                    try
                    {
                        //если ошибки нет, забираем данные из ответа
                        var auth = authService.CheckToken(AuthToken);
                        AuthToken = auth.AuthToken;
                        SessionToken = auth.SessionToken;
                    }
                    catch (FaultException<AuthorizationService.PublicServiceException> ex)
                    {
                        if (ex.Detail.StatusCode == 401)
                        {
                            //если в запросе произошла ошибка авторизации, заново получаем данные для авторизации
                            WebOperationContext.Current.OutgoingRequest.Headers.Add("ApplicationToken", ApplicationToken);
                            WebOperationContext.Current.OutgoingRequest.Headers.Add("SessionToken", SessionToken);
                            var token = authService.LoginWithUserName("admin", "");
                            AuthToken = token.AuthToken;
                            SessionToken = token.SessionToken;
                        }
                        else
                        {
                            //иначе выбрасываем ошибку или дальше её обрабатываем
                            throw;
                        }
                    }
                }

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

Отловив эту ошибку, можно получить следующую информацию:

  1. Сообщение об ошибке.
  2. Веб-код ошибки (пример: 400, 401, 500).
  3. Внутреннюю ошибку (если таковая имеется).

и многое другое.

Наиболее часто попадаются ошибки с кодом 401 и 500. Ошибка с кодом 401 падает в том случае, когда авторизация не удалась. Чаще всего причиной для неё могут быть:

  1. Неверный логин\пароль.
  2. Устаревший\несуществующий токен авторизации.
  3. Несуществующий токен сессии.
  4. Неправильный токен приложения.

Ошибка с кодом 500 связана с внутренней ошибкой сервера. Чаще всего причиной для неё могут быть:

  1. Ошибка при исполнении кода на сервере.
  2. Отсутствие конкретного объекта (пример: использование функции Load).
  3. Отсутствие определённого типа объекта (когда typeUid не существует).

Теоретически возможны ошибки и с другими кодами, но они очень редкие.

Переходим к загрузке задачи. Добавим в созданный класс функцию LoadTask().

    public void LoadTask()
    {
        var entityService = _entityServiceFactory.CreateChannel();
        var typeUid = "f532ef81-20e1-467d-89a4-940c57a609bc";
        var id = "37";

        using (new OperationContextScope((IContextChannel)entityService))
        {
            WebOperationContext.Current.OutgoingRequest.Headers.Add("AuthToken", authToken.ToString());
            WebOperationContext.Current.OutgoingRequest.Headers.Add("SessionToken", sessionToken);
            var task = entityService.Load(typeUid, id);

            foreach (var item in task.Items)
            {
                Console.WriteLine(item.Name + ": " + item.Value);
            }
        }
        Console.ReadKey();
    }

Результат выполнения:

Id: 37
TypeUid: f532ef81-20e1-467d-89a4-940c57a609bc
Uid: e44c7deb-9f9c-4cc5-8034-90906e13149a
Subject: Задача для тестирования веб сервиса
CreationDate: 10/31/2015 19:52:57
CreationAuthor:
Executor:
StartDate: 10/31/2015 00:00:10
EndDate: 11/04/2015 23:59:50
Status: dd048b73-4e08-404a-b62e-c55222845cc4
StartWorkDate:
EndWorkDate: 10/31/2015 23:33:17
InformTo:
Category:
ExpiredNotificationSent: False
IsEmulation: False
AssignedToResponsible: False

Здесь представлена лишь часть полей, возвращаемых функцией.

Замечание

При выполнении некоторых функций может отобразиться следующая ошибка:

"Необработанное исключение типа "System.ServiceModel.CommunicationException" в mscorlib.dll

Дополнительные сведения: Превышена квота максимального размера сообщения для входящих сообщений (65536). Для увеличения квоты используйте свойство MaxReceivedMessageSize соответствующего элемента привязки".

Это происходит потому, что ответ от сервера приходит слишком большой, и ограничение на вашем приложении не может его пропустить. Чтобы этого избежать, используйте инициализацию переменных _entityServiceFactory следующим образом:
_entityServiceFactory = new ChannelFactory<EntityService.IEntityServiceChannel>(new BasicHttpBinding() { MaxReceivedMessageSize = Int32.MaxValue }, "http://localhost:2016/API/Entity");

Версия API 1.0.1 в ELMA 3.2

В версии системы 3.2.0 версия API обновилась до 1.0.1. Вы можете узнать подробнее об изменениях.

Далее ознакомьтесь со следующими статьями:

Прикрепленные файлы