четверг, 13 ноября 2014 г.

SharePoint 2013 Workflow: HttpSend и DynamicValue

Сегодня я остановлюсь подробнее о ключевой активности при работе с workflow - активности HttpSend. Эта активность является ключевой, потому что приходиться постоянно работать с службами данных, так как собственно других средств для процесса, запущенного в отдельной ферме внутри Workflow Manager, не существует. Активность HttpSend разработана специально для SharePoint и появляется в Visual Studio только в проекте SharePoint 2013, хотя и является универсальной. То есть её вполне можно использовать для запросов к другим разработанным службам данных. Её особенность при работе с SharePoint состоит в том, что эта активность автоматически устанавливает заголовок Authorization: Bearer для аутентификации с помощью OData, в остальном же это обычный запрос с помощью WebRequest.

Рассмотрим работу с активностью HttpSend подробнее. Для начала рассмотрим работу со стандартным сервисом SharePoint.

В первом примере я получаю список приложенных файлов. Адрес запроса для получения списка файлов можно получить из возвращаемого свойства элемента AttachmentFiles/__deferred/uri:
Получив url, отправляем запрос с помощью HttpSend:
Сначала получаем токен S2S с помощью активности GetS2SSecurityToken и сохраняем его в переменной типа SecurityToken. Этот токен подставляем в параметр активности SecurityToken.
Так как у нас будут возвращены комплексные данные, то работать будем с ними с помощью переменной типа DynamicValue. Для этого заводим переменную этого типа attachments. Активность HttpSend имеет следующую приятную особенность: если задать на вход в параметр RequestContent переменную типа DynamicValue, то в тело запроса автоматически вставится JSON и добавится заголовок HTTP Content-Type: application/json; odata=verbose. Также, если задать в выходном параметре ResponseContent переменную типа DynamicValue, то автоматически добавится заголовок HTTP Accept: application/json; odata=verbose, а возвращённый сервером результат в виде JSON будет разобран и помещён в переменную. Поэтому в нашем примере мы получаем структуру данных со списком вложенных файлов сразу в переменной attachments типа DynamicValue.
Для контроля результатов запроса мною используется выходное свойство ResponseStatusCode, которое позволяет сохранить статус ответа HTTP в переменной типа HttpStatusCode.
Для перебора массива в сложной структуре DynamicValue удобнее всего использовать активность ForEach<T>. В нашем примере список файлов возвращается в структуре d/results, для её перебора используем конструкцию: attachments["d"]["results"].

Во втором примере я запрашиваю свой сервис данных WCF. Мне необходимо обновить несколько полей в сущности Equipment (которая фактически является таблицей в базе данных). Для формирования структуры данных, которую мы будем отсылать в сервис, будем использовать тот же самый DynamicValue. Для этого создаём переменную equipmentProperties и инициализируем её с помощью активности BuildDynamicValue:
Сама обновляемая сущность у нас адресуется примерно таким образом: /service.svc/Equipment(guid'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXX'), где guid - это уникальный идентификатор в таблице. Обновление сущности целиком (всех полей) надо производить с помощью метода PUT. Но, так как мы ходим обновить только несколько полей, то для этого необходимо использовать специальный метод MERGE, который описан в стандарте OData. В выпадающем списке входного параметра Method активности HttpSend такого метода нет, чтобы его задать нужно просто кликнуть на кнопку с тремя точками и воспользоваться текстовым редактором.
Для успешной аутентификации в службе данных обязательно задаём заголовок HTTP Athorization: "" (пустая строка) для того, чтобы сбросить значение Bearer, которое автоматически задаётся (о чём было написано выше).
При успешном обновлении данных сервисом возвращается код 204 (No Content), что я и проверяю после вызова.

Это всё, что хотел рассказать сегодня. Всем удачных разработок!