Описание

В D365O, по сравнению с AX2012, была добавлена возможность подключения к развернутым по-умолчанию веб-сервисам OData. Веб-сервисы этого типа позволяют считывать и модифицировать данные всех data entity D365O, настройки которых позволяют это делать. Считывание данных происходит в формате JSON.

Для считывания данных, клиент отправляет на веб-сервисы GET запросы, в которых указывает то, какие данные из data entity он хочет получить. При этом доступна фильтрация по каждому из полей data entity, в том числе и по полям, входящим в другие поля. Подробно о возможных запросах можно прочитать в документации протокола OData , доступной по следующей ссылке: http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Toc453752278. Далее из всего функционала по работе с data entity через веб-сервисы приведена информация только по фильтрации и выборке выводимых полей.

Базовым запросом к веб-сервисам OData является запрос вида «АДРЕС D365O»/data. Например, https://oit-adm-boryseda2b5401719f08ddevaos.cloudax.dynamics.com/data. При этом возвращается список названий всех data entity в D365O. При чем, выведенные названия – это не названия файлов data entity в AOT, а PublicCollectionName, указанные в параметрах этих файлов.

При добавлении к базовому запросу названия одной из data entity указаных в списке (запрос вида «АДРЕС D365O»/data/«НАЗВАНИЕ DATA ENTITY»), выводятся все значения, содержащиеся в data entity, у которых компания соответствует компании пользователя, под чьей учетной записью был получен доступ к веб-сервису. Например: https://oit-adm-boryseda2b5401719f08ddevaos.cloudax.dynamics.com/data/ReleasedProductMasters.

Для получения данных всех компаний, необходимо добавить параметр cross-company=true: «АДРЕС D365O»/data/«НАЗВАНИЕ DATA ENTITY»?cross-company=true. Например: https://oit-adm-boryseda2b5401719f08ddevaos.cloudax.dynamics.com/data/ReleasedProductMasters?cross-company=true.

Для получения данных по конкретной компании, помимо указания cross-company=true, необходимо использовать фильтрацию.

Фильтрация в протоколе OData осуществляется с помощью добавления к строке URL параметра $filter=. После знака равенства указываются все условия фильтрации. При построении условий фильтрации могут использоваться следующие операторы:

Операторы сравнения:

  • 1. eq (равно).

  • 2. ne (не равно).

  • 3. gt (больше).

  • 4. ge (больше или равно).

  • 5. lt (меньше).

  • 6. le (меньше или равно).

  • 7. has (содержит значение (например, Style has Sales.Color’Yellow’)).

Логические операторы:

  • 1. and (и).

  • 2. or (или).

  • 3. not (не).

Арифметические операторы:

  • 1. add (суммирование).

  • 2. sub (вычитание).

  • 3. mul (умножение).

  • 4. div (деление).

  • 5. mod (остаток от деления).

Операторы группировки: ().

Самый простые условия выглядят так: «НАЗВАНИЕ ПОЛЯ» «ОПЕРАТОР СРАВНЕНИЯ» «ЗНАЧЕНИЕ» «ЛОГИЧЕСКИЙ ОПЕРАТОР» «НАЗВАНИЕ ПОЛЯ» «ОПЕРАТОР СРАВНЕНИЯ» «ЗНАЧЕНИЕ». Например, добавив условия фильтрации к указанному раннее URL, получаем: https://oit-adm-boryseda2b5401719f08ddevaos.cloudax.dynamics.com/data/ReleasedProductMasters?cross-company=true&$filter=ItemNumber eq ‘M0008’ and BOMLevel eq 0 and dataAreaId eq ‘USMF’. Как видно, последнее из полей в даной строке – dataAreaId, которое отвечает за выбор компании.

При фильтрации по текстовым полям, нужно использовать одинарные кавычки ‘ ’ вокруг значения.

При фильтрации по числовым полям, значение записывается без кавычек.

При фильтрации по значению enum полей, используется синтаксис вида: «NAMESPACE, К КОТОРОМУ ОТНОСИТСЯ ENUM».«НАЗВАНИЕ ENUM»’«ЗНАЧЕНИЕ ENUM»’. Например, значение может выглядеть следующим образом: System.Web.OData.TestCommon.Models.Gender’Male’.

Стоит отметить, что при переходе в браузере по URL, в котором указаны условия фильтрации, вид этого URL изменяется, заменяя символы пробела на %20, а символы одинарных кавычек на %27. Волноваться по этому поводу не нужно, — можно даже комбинировать в запросе указанные выше обозначения этих знаков и их нормальное обозначение, при этом запрос должен отработать корректно.

Описанные выше условия отфильтровывают результат, идущий на выход сервиса, но при этом клиентская программа все еще получает все поля, относящиеся к оставшимся после фильтрации data entity. Чтобы указать, какие конкретно поля нужно возвращать, в запросе URL используется параметр $select=. После знака равенства необходимо через запятую, слитно, перечислить необходимые поля. Например: $select=ItemNumber,BOMLevel.

Таким образом, запрос для одновременной фильтрации и выборки выглядит, например, следующим образом: https://oit-adm-boryseda2b5401719f08ddevaos.cloudax.dynamics.com/data/ReleasedProductMasters?cross-company=true&$select=ItemNumber,BOMLevel,dataAreaId&$filter=ItemNumber eq ’M0008’ and BOMLevel eq 0.

При возникновении необходимости в формировании более сложных запросов, рекомендую ознакомиться с документацией. OData поддерживает большой набор встроенных функций, — от обрезки строк до математических округлений и выделения лет, месяцев, дней и времени из дат.

На выходе OData вебсервисов D365O используется JSON следующей структуры:

  • 1. value – массив, содержащий информацию о каждой возвращенной записи data entity. Данные в массиве содержат все public поля data entity, а также хеш код записи @odata.etag.

  • 2. @odata.context –адрес источника данных.

Вызов только считывающего данные веб-сервиса D365O из Desktop приложения

Подготовительный этап

Основной код

При использовании вспомогательного проекта JsonRequestSender, вызов вебсервиса сводится к одной команде. Для этого сначала нужно создать объект класса RequestSender_OAuth, так как в вебсервисах D365O используется аутентификация OAuth.

Copy to Clipboard

Далее, так как считать данные из OData вебсервисов D365O можно с помощью GET запросов, отправляем GET запрос, по правилам запросов OData.

Copy to Clipboard

В метод sendGETRequest() передаются один дженерик класс и один аргумент.

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

Аргумент определяет относительный адрес вызываемого метода вебсервиса в ресурсе. В данном случае относительный адрес показывает, что нужно вернуть записи из data entity с PublicCollectionName GoalHeadings, по всем компаниям.

Пример

В качестве примера приведено приложение Microsoft forms для получения данных из data entity HcmGoalHeadingEntity D365O.

Copy to Clipboard

Вызов полнофункционального веб-сервиса D365O из Desktop приложения

Подготовительный этап

Основной код

Класс сервиса

Не зависимо от того, нужно ли найти, создать, обновить или удалить запись в data entity, первым делом нужно создать класс, наследующий вспомогательный класс ODataServiceBase из проекта ODataProxy. Например:

Copy to Clipboard

Все операции должны быть объявлены в этом классе, так как он настроен на работу со всеми data entity системы, к которой нужно подключиться.

Создание данных

Для создания новой записи, создается и заполняется значениями объект нужной data entity из прокси класса. При этом нужно заполнить все обязательные поля data entity.

Copy to Clipboard

Далее у OData клиента, созданного на основе прокси класса, вызывается метод AddObject, в котором первым параметром передается PublicCollectionName data entity, а вторым – переменная контракта данных data entity.

Copy to Clipboard

После этого запрос отправляется на сервер, желательно в try-catch:

Copy to Clipboard

Считывание данных

Для считывания данных по data entity нужно выполнить Linq запрос для выбранной в переменной клиента data entity.

При этом результат нужно преобразовать в DataServiceCollection для корректной отработки операции обновления. Это позволит клиенту отправлять PATCH запросы вместо PUT для обновления данных, что предотвратит ошибки при наличии в data entity закрытых на редактирование полей.

Запрос лучше отправлять в try-catch.

Copy to Clipboard

Рассмотрим часть Linq запроса:

Copy to Clipboard

Этот запрос означает, что из клиента OData вызывается считывание данных по data entity с PublicCollectionName PurchaseOrderHeadersV2, и при этом должны вернутся такие записи, у которых поле PurchaseOrderNumber соответствует некоторой переменной purchId, или же записи вне зависимости от PurchaseOrderNumber, если переменная purchId содержит пустую строку.

Таким образом можно отфильтровать результат по любым полям data entity.

Вне зависимости от того, преобразовывался ли результат запроса в рекомендуемый класс DataServiceCollection, по полученным значениям можно пройти с помощью цикла foreach.

Copy to Clipboard

Изменение данных

Для изменения данных data entity, их сначала нужно получить. То есть, сначала необходимо выполнить все шаги описанные в инструкции по считыванию данных.

Далее нужно изменить некоторые поля.

Copy to Clipboard

После этого запрос отправляется на сервер, желательно в блоке try-catch:

Copy to Clipboard

Удаление данных

Для удаления данных data entity, их сначала нужно получить. То есть, сначала необходимо выполнить все шаги описанные в инструкции по считыванию данных.

Далее для указания OData клиенту того, что data entity должна быть удалена при выполнении запроса, вызывается метод DeleteObject, в который передается полученная переменная контракта данных data entity.

Copy to Clipboard

После этого запрос отправляется на сервер, желательно в блоке try-catch:

Copy to Clipboard

Пример

В качестве примера приведено приложение Microsoft forms для получения, создания, обновления и удаления данных из data entity PurchPurchaseOrderHeaderV2Entity D365O.

В случае получения данных, поля над кнопками служат фильтрами и не обязательны для заполнения.

Для создания новых записей и для обновления существующих все поля должны быть заполнены. При этом при обновлении будет найдена запись с указанным Purch id и все остальные ее поля будут обновлены.

Для удаления записи достаточно указать ее Purch id.

Copy to Clipboard

Подготовил статью:

Дыкуха
ДыкухаБорис Александрович
Senior Software Developer, OntargIT
Published On: 16 апреля, 2021 / Рубрики: Blog /

Следите за новостями компании OntargIT

    Ознакомиться с Политикой конфиденицальности можно здесь.