Что такое odata
Перейти к содержимому

Что такое odata

  • автор:

Кратко об OData

Привет, Хабр! Недавно, пришлось работать на проекте с внешним API. Работал, я, к слову, всегда либо с простым REST, либо с GET/POST only запросами, но в этом нужно было работать с API Timetta. Он использует OData и что же это такое?

REST vs OData

В то время как REST — набор архитектурных правил создания хорошего API, OData — это уже веб-протокол, собравший в себя «лучшие архитектурные практики»: defines a set of best practices for building and consuming RESTful APIs (как написано на официальном сайте). Сам протокол очень большой, поэтому я затрону наиболее практически-значимые аспекты.

Схема

Каждая система использующая OData должна описать свою схему данных. По ней можно понять все: какие сущности есть в системе, какие операции над ними можно производить. Схема может описывается в формате XML или JSON. Для получения схемы нужно сделать запрос по адресу:

Где — корень сервиса OData. Примеры дальше будут предполагать, что мы делаем запросы из этого . Для Timetta этот адрес такой:

Примеры дальше будут с использованием XML схем.

Типы данных

Примитивные

Протокол определяет ряд встроенных типов данных. Все имеют префикс «Edm». Например:

  • Edm.Boolean
  • Edm.String
  • Edm.Int32
  • Edm.Int16
  • Edm.Stream
  • Edm.Date
  • Edm.Byte
  • Edm.Decimal
  • Edm.Binary

EntityType

EntityType похож на сущность из DDD: у него есть как состояние, так и свой ID (в схеме указывается отдельно). В схеме состоит из элементов

  • Property — поля со скалярными данными. Например, строка или число. Имеет атрибуты:
    • Name — название поля (обязателен)
    • Type — тип поля (обязателен)
    • Nullable — может ли быть null
    • Name — название (обязателен)
    • Type — тип (обязателен)
    • ReferentialConstraint — «как» мы ссылаемся
      • Property — название поля в ССЫЛАЮЩЕМСЯ типе
      • ReferencedProperty — название поля в типе, на который ССЫЛАЕМСЯ
      • Name — название поля, которое является ключом
      • Alias — псеводним для ключа. Например, если ключ — поле вложенного типа.

      Пример, для сущности TimeSheet, представляющей рабочий график проекта (табель) за некоторый период времени.

      • Поле «id» — первичый ключ
      • Имеет несколько полей с примитивными типами. Например:
        • dueDate — до какой даты нужно закончить
        • dateFrom — когда начинать проект
        • dateTo — когда оканчивать проект
        • approvalInstanceId — Id документа (ресурса), который сигнализирует о том, что работа согласована (если не согласован, то значение — null, нет атрибута Nullable, что по умолчанию означает поддержку null)

        Некоторые из которых могут принимать значение null:

        • dueDate — мы еще не знаем дедлайн
        • approvalInstanceId — работу еще могли не согласовать
        • approvalInstance — документ согласования
        • timeSheetLines — потраченные часы
        • createdBy — кем создан план работ
        • approvalInstance можно найти по занчению поля approvalInstanceId родителя и сопоставление по полю id искомой сущности
        • timeSheetLines — «слабая» сущность. Для нее не нужен Id, время жизни привязано к самому родителю

        ComplexType

        ComplexType похож на Value type из DDD — не имеет первичного ключа, сравнение по значению полей. Может состоять из тех же элементов, что и EntityType за исключением Key.

        Пример, для объекта с 2 полями, который используется для отметок времени

        • Тип DateHours является сложным (ComplexType)
        • Состоит из 2 полей:
          • date — дата (Type=»Edm.Date»), за которую идет отсчет.
          • hours — время, представляемое дробным числом (Type=»Edm.Decimal»)
          • date — не может быть null, т.к. мы должны знать дату
          • hours — может быть null, т.к. время может быть просто не проставлено/указано

          EnumType

          EnumType — обычный тип перечисления. Особенность в том, как передается значение в параметры — сначала пишется полное имя Enum, затем в кавычках его значение. Для данного примера, чтобы передать PlanningMethod.Manual , нужно написать PlanningMethod’Manual’ . Атрибуты:

          • Name — название перечисления (обязательно)
          • UnderlyingType — тип, которое определяет используемое значение (по умолчанию, Edm.Int32)
          • IsFlags — является ли перечисление флагом. Чтобы исползовать в UnderlyingType должно быть проставлено «true»

          Для определения занчений — элемент Member:

          • Name — название элемента
          • Value — значение элемента
          • Тип PlanningMethod является типом перечисления (EnumType)
          • Может принимать значения:
            • Manual, определяемое значением 0
            • FrontLoad, определяемое значением 1
            • RemainingCapacity, определяемое значением 2
            • Evenly, определяемое значением 3

            P.S. В общем случае такой вид записи применяется ко всем типам и имеет вид: ПолныйТипСущности’Значение’. Например, для даты — date’2022-07-01′

            Collection

            Тип коллекции является отдельным. Определяется как Collection(ПолноеНазваниеТипа) . Например, Collection(WP.TimeSheet) .

            Возвращаясь к типу TimeSheet. В нем присутствуют 5 коллекций*:

            • timeSheetLines
            • timeAllocations
            • lineApprovals
            • approvalRecors
            • timeOffRequests

            *Тип коллекции может быть и у Property, не только NavigationProperty

            EntitySet

            У нас есть сущности, сложные типы, перечисления и т.д. Но где это хранить? Для этого нам нужна коллекция.EntitySet — это top-level коллекция доступная всем. Внутри нее хранятся какие-либо сущности. Соответственно, для нее обязательны имя и тип: Name=»SampleName» EntityType=»SampleType», соответственно. По умолчанию, все обычные поля (Property) коллекции включаются в вывод. Если у типа есть навигационные свойства, то их должны указать в EntitySet, иначе их существование не гарантируется.

            • Name=»TimeSheets» — название коллекции. Доступ к ней через это слово: https://app.timetta.com/TimeSheets
            • EntityType=»WP.TimeSheet» — тип сущностей используемый в коллекции (был выше). WP — пространство имен.
            • У коллекции есть несколько навигационных свойств. Свойства — те же, что и у самой сущности. Например:
              • user
              • template
              • modifiedBy

              Но некоторые (total, lineApprovements) отсутствуют.

              Есть коллекция, значит есть и единственный элемент. Для получения нужно использовать ID сущности, который указан в схеме. Указывать в круглых скобках после названии коллекции. Например, для получения TimeSheet то его ID нужно сделать запрос:

              Запросы

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

              Сам запрос передается в строке запросов (query string) URL. Например:

              /TimeSheets?$select=id,dateFrom,dateTo&$filter=approval&$expand=createdBy($select=name)&$count=true

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

              Поэтому, многие запросы OData транслируются в SQL. У этого языка много ключевых слов, но рассмотрим основные. Для лучшего погружения представим ситуацию: нам нужно получить отчеты.

              $select

              $select позволяет нам выбрать только нужные поля.

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

              /TimeSheets?$select=dateFrom,dateTo,id

              $filter

              Прекрасно. Мы получили данные. Но что если какие-то табеля не были согласованы? Нужно убрать такие:

              /TimeSheets?$select=dateFrom,dateTo,id&$filter=approvalInstanceId ne null

              Какой-то табель не был согласован! Хорошо, что мы обнаружили это.

              Сам $filter принимает в себя логическое выражение. Доступные логические операции (bash-like):

              • eq (equal), ==: name eq ‘За ноябрь’
              • ne (not equal), !=: approvalInstanceId ne null
              • gt (greater than), >: dueDate gt ‘2022-03-15’
              • ge (greater or equal), >=: dateFrom ge ‘2021-01-01’
              • lt (less than),
              • le (less or equal),

              Эти выражения можно комбинировать с помощью скобок и:

              • and (логическое ‘и’): (name eq ‘За ноябрь’) and (dateFrom ge ‘2021-01-01’)
              • or (логическое ‘или’): ( dateFrom ge ‘2021-01-01’) or (approvalInstanceId ne null)
              • not (отрицание): not isActive

              Также есть и булевы литералы: true , false

              $expand

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

              /TimeSheets?$select=dateFrom,dateTo,id&$filter=approvalInstanceId ne null&$expand=user($select=name)

              Здесь продемонстрированы сразу 2 фичи:

              1. Возможность вставить сущность из навигационного свойства (у типа TimeSheet есть навигационное свойство user типа WP.User)
              2. Сделать подзапросы: здесь из всех возможных свойств нам нужно только имя. Для подзапросов есть ограничения — ключевые слова разделяются точкой с запятой, иначе парсинг строки запроса будет неверным. Например: /TimeSheets?$select=dateFrom,dateTo,id&$filter=approvalInstanceId ne null&$expand=user($select=name;$expand=schedules) — дает нам не только имя пользователя, но и список его рабочих графиков. Если бы вместо точки с запятой был амперсанд, то получилось бы 2 параметра: $expand=user($select=name и $expand=schedules)

              $orderby

              Вроде бы все прекрасно. Данные получаются, но мы хотим получать упорядоченные данные сразу. Нам поможет ключевое слово $orderby. Представим, что мы хотим сортировать табели сначала по дате начала по убыванию, а затем по дате конца по возрастанию (получим самые близкие к нам по дате, короткие по длительности):

              /TimeSheets?$select=dateFrom,dateTo,id&$filter=approvalInstanceId ne null&$expand=user($select=name)&$orderby=dateFrom desc, dateTo asc

              По умолчанию используется сортировка по возрастанию — asc

              $top, $skip

              Вот проблема! У нас слишком много данных. Как бы нам ограничить их прием? Для этого можно указать какое количество мы хотим принять с помощью $top. Тогда нам вернется не больше заданного количества:

              /TimeSheets?$select=dateFrom,dateTo,id&$filter=approvalInstanceId ne null&$expand=user($select=name)&$orderby=dateFrom desc, dateTo asc$top=5

              А что если нужно еще и пропускать некоторое количество (для пагинации, например)? Тогда используем $skip:

              /TimeSheets?$select=dateFrom,dateTo,id&$filter=approvalInstanceId ne null&$expand=user($select=name)&$orderby=dateFrom desc, dateTo asc&$top=5&$skip=10

              $count

              Мы можем получить наши данные — прекрасно. А если я хочу знать только количество удовлетворяющих критерию? Или для пагинации? Нужно посчитать общее количество элементов. Здесь нам поможет $count. Он принимает булево значение: true — вернуть общее количество, false — не возвращать (по умолчанию)

              /TimeSheets?$select=dateFrom,dateTo,id&$filter=approvalInstanceId ne null&$expand=user($select=name)&$orderby=dateFrom desc, dateTo asc&$count=true

              Функции, действия

              Вот здесь начинается самое интересное — функции и действия (Functions, Actions). Теперь мы хотим получить табель за текущий период. Можно получить все табеля и отфильтровать их — сделать сложный запрос, а потом отфильтровать еще и результат. Это лишнее. Не проще ли использовать функцию:

              /TimeSheets/Current

              OData определяет функции (Function) и действия (Action)

              Function — это операция над ресурсами, которая обязательно возвращает значение и не имеет сторонних эффектов.

              Action — это операция, которая может изменить значение

              PS. похоже на CQRS

              Как же ими пользоваться? Для начала: операции могут быть привязанными и нет — требуется ли сущность для выполнения операции. Описание операции состоит из

              Функция из примера имеет следующее пределение:

              Что это все значит:

              1. Name=»Current» — название функции, которую будем вызывать
              2. IsBound=»true» — функция привязана к конкретному типу. Т.е. вызвать ее из произвольного места нельзя
              3. «bindingParameter» — особый параметр означающий к какому типу функция применяется. Здесь применяется к типу Collection(WP.TimeSheet) (чем и является /TimeSheets )
              4. Возвращает тип TimeSheet

              Если функция не принимает ничего, то скобок нет. Видели. А если функция принимает параметры? Тогда они указываются в элементе Parameter :

              Эта функция принимает дополнительные параметры: userId, from, to (в данном случае они обязательные — Nullable=»false»). Передача параметров — как вызов функции, в скобках, причем все параметры именованные и вставляются через запятую (как в Python). Пример:

              /Schedules/GetUserSchedule(userId=00000000-0000-0000-0000-00000000,from=2022-01-01,to=2022-02-01) — получение расписания для пользователя за весь январь

              Что по Action? Разница в том, что действие может модифицировать данные и может не возвращать данные. Например:

              Это действие устанавливает тип роли пользователя применяемой по умолчанию. Логично, что оно может модифицировать, а может и нет (если это тип уже был по умолчанию). Также он ничего не возвращает (разве что статусный код по которму и будет понятен результат). Как вызывать:

              Это привязанное действие и привязано оно к типу WP.Role, а значит к единственному элементу, а не к целой коллекции как было в предыдущем примере.

              Пример действия, который что-то возвращает:

              Модификация ресурсов

              Для операций модификаций ресурсов используются HTTP методы: POST, PATCH, PUT, DELETE

              Создание

              Создание сущности = добавление в коллекцию. Для этого нужно сделать POST запрос с адресом коллекции и передать необходимые для создания параметры. Например, для создания нового департамента нужно сделать такой POST запрос:

              И в ответ получим:

              Обновление

              Для обновления используются 2 HTTP метода: PUT, PATCH (последний предпочтительнее). Если бы мы хотели обновить название только что созданного департамента на «Лучший департамент», то сделали такой запрос:

              И в ответ — 204 No Content

              При повторном запросе:

              Название действительно изменилось. Также изменилось и поле «rowVersion» — для предотвращение параллельного обновления.

              Но говорилось еще и о PUT. При использовании PUT нам нужно передавать ВСЮ сущность. Даже те поля, которые не обновляются (за исключением тех над которыми не имеем власти, например, rowVersion или modified). Тоже самое обновление, но с помощью PUT:

              Удаление

              И для удаления остался последний метод — DELETE. Удаление через ID сущности. Удалим же наш департамент:

              В ответ получим — 204 No Content. И при обращении по этому же ID получаем Not Found.

              Подытожим

              OData — мощный веб-фреймворк, ядром которого является управление ресурсами.

              Для функционирования использует возможности HTTP: HTTP методы, HTTP заголовки, строки запроса, URL.

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

              • Типы данных:
                • Перечисления, Enum
                • Сложные типы, ComplexType
                • Сущности, EntityType
                • Свойства (и свойства свойств (Nullability, MaxLength)
                • Навигационные свойства
                • Специфичные для данного типа атрибуты: ключ для сущности, значения для перечисления

                Сам протокол определяет SQL подобный язык запросов (передается в строке запроса) и позволяет управлять получаемым контентом с помощью ключевых слов:

                • $select — в выводе только указанные поля. (~ SELECT)
                • $filter — вывести ресурсы, удовлетворяющие предикату (~ WHERE)
                • $expand — включить другие ресурсы, на который ссылается (~JOIN)
                • $orderby — сортировка по полю. (~ORDER BY)
                • $top — ограничить вывод максимальным количеством. (~TAKE)
                • $skip — пропустить какое-то количество. (~SKIP, OFFSET)
                • $count — дополнительно подсчитать общее число (или удовлетворяющих предикату) сущностей. (~COUNT)

                Напоследок

                OData очень большой фреймворк. Одна статья не может покрыть его полностью. Но целью этого поста стало простое ознакомление с наиболее используемой (по мнению автора) функциональностью. Многие темы не были покрыты, как например ключевое слово запроса $compute или лямбда операций any/all. Если вы хотите исследовать эту тему дальше, то вот некоторый список ссылок от куда можно стартовать:

                • https://www.odata.org — сайт по OData. Здесь можно найти спецификацию, туториалы для новичков и продвинутых, полезные инструменты и так далее.
                • https://docs.microsoft.com/en-us/odata — раздел об OData созданный Microsoft. Здесь много туториалов как по самому OData, так и по инструментам связанным с ним. Много уделяется фреймворку Microsoft.OData.
                • https://services.odata.org/ — сервис, для обучения/тестирования/просто попробовать OData. Как пользоваться для Read-Only Service:
                  1. Устанавливаю базовый URL https://services.odata.org/V3/OData/OData.svc/
                  2. Мне удобнее получать результат в виде JSON. Поэтому выставляю заголовок Accept: application/json
                  3. Получаю схему OData: https://services.odata.org/V3/OData/OData.svc/$metadata
                  4. Изучаю полученную схему и делаю запросы.
                  5. Для получения списка всех продуктов по схеме нужно делаю такой запрос: https://services.odata.org/V3/OData/OData.svc/Products Read-Only Northwind пользоваться по аналогии

                Если нужно потренироваться и в модификации, то есть Read-Write. Для этого нужен ваш секретный ключ. Получить его можно, перейдя по ссылке Browse the Full Access (Read-Write) Service на указанном сайте. В браузере ваша строка заменится на строку с ключом. Либо, эту строка указывается в полученной схеме. Сам вид строки: https://services.odata.org/V3/(S())/OData/OData.svc . А в запросах на создание (POST) нужно также указывать тип ресурса, который хотим создать в поле «odata.type» (там используется наследование, про которое не было рассказано). Например, для создания нового Product сделать вот такой запрос:

                Пример для Timetta. Как получить адрес схемы было в начале.

                • Расширение VS Code для работы с OData.
                • Веб-приложение для визуализации и исследования OData, по ее схеме. Использование: в верхней части в поисковике выберите вариант ‘Metadata URL’. Вбейте в поисковик URL и нажмите ‘Get Details’.

                Триггером написания статьи было, то что автор не нашел «краш курсов» по OData и пришлось собирать знания по кусочкам. Если статья дала вам хороший старт, то значит проделанное было не зря.

                • Веб-разработка
                • Поисковые технологии
                • Data Mining
                • Открытые данные

                OData

                OData (Open Data Protocol) — это утвержденный ISO/IEC стандарт OASIS, который определяет набор лучших практик для построения и использования REST API. Протокол позволяет создавать службы на основе REST, которые с помощью HTTP-запросов предоставляют веб-клиентам возможность публиковать и редактировать ресурсы, идентифицированные с использованием URL и определенные в модели данных.

                Назначение протокола OData — выполнение запросов от внешних приложений к серверу баз данных Creatio.

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

                Для выполнения внешних запросов к приложению Creatio необходимо выполнить аутентификацию. При интеграции по протоколу OData Creatio позволяет использовать Forms-аутентификации и OAuth-аутентификацию. Интеграция по протоколу OData не поддерживает аутентификацию по протоколу LDAP. Рекомендуемым способом аутентификации для интеграции с приложением по протоколу OData является Forms-аутентификация, которая реализована с помощью веб-сервиса AuthService.svc . Виды аутентификации, которые поддерживаются в Creatio, описаны в статье Аутентификация. Чтобы настроить авторизацию по протоколу OAuth, воспользуйтесь инструкцией, которая приведена в статье Настроить авторизацию интегрированных приложений по протоколу OAuth 2.0.

                Протокол OData 4

                Доступ к объектам Creatio по протоколу OData 4 предоставляет веб-сервис odata .

                https://mycreatio.com/0/odata
                https://mycreatio.com/odata

                Протокол OData 3

                Доступ к объектам Creatio по протоколу OData 3 предоставляет веб-сервис EntityDataService.svc .

                Адрес сервиса EntityDataService.svc

                https://mycreatio.com/0/ServiceModel/EntityDataService.svc

                Сервис EntityDataService.svc предоставляет возможность работы с объектами Creatio в WCF-клиенте.

                Windows Communication Foundation (WCF) — программный фреймворк в составе .NET Framework, который используется для обмена данными между приложениями.

                Организация работы WCF-клиента реализована путем получения метаданных сервиса и создания клиентских прокси-классов. Клиентское приложение использует эти классы-посредники для работы с сервисом EntityDataService.svc Creatio.

                Чтобы реализовать клиентское приложение:

                1. Создайте .NET-проект, в котором реализована интеграция с Creatio.
                2. Сгенерируйте клиентские прокси-классы сервиса EntityDataService.svc .
                3. Создайте экземпляр контекста среды выполнения сервиса EntityDataService.svc .
                4. Реализуйте клиентскую бизнес-логику интеграции с использованием методов созданного экземпляра прокси-класса.

                Способы генерации прокси-классов сервиса EntityDataService.svc :

                • C использованием утилиты DataServiceModel Metadata Utility Tool (DataSvcutil.exe) .
                • Из проекта клиентского приложения Visual Studio.

                Генерировать прокси-классы с использованием утилиты DataServiceModel Metadata Utility Tool

                DataSvcUtil.exe — программа командной строки, которая предоставлена сервисами WCF Data Services . Утилита использует канал OData для формирования клиентских классов службы данных, которые необходимы для доступа к службе данных из клиентского приложения .NET Framework.

                Источники метаданных, которые утилита использует для формирования классов данных:

                • WSDL — документ метаданных службы. Описывает модель данных, которая предоставлена службой данных.
                • CSDL — файл модели данных. Используется язык определения концептуальной схемы ( CSDL ), который описан в спецификации [MC–CSDL]: формат файла определения концептуальной схемы.
                • EDMX — *.xml-файл. Создается с помощью программ для работы с моделью EDM , которые входят в комплект Entity Framework . Дополнительные сведения описаны в спецификации [MC–EDMX]: модели EDM для формата упаковки служб данных.

                Обычно утилита DataSvcUtil.exe установлена в каталоге C:\Windows\Microsoft.NET\Framework\v4.0 . Для 64-разрядных версий систем это каталог C:\Windows\Microsoft.NET\Framework64\v4.0 .

                Формат вызова утилиты DataSvcutil.exe

                datasvcutil /out:file [/in:file | /uri:serviceuri] [/dataservicecollection] [/language:devlang] [/nologo] [/version:ver] [/help]

                Детальная информация по утилите DataSvcutil.exe приведена в официальной документации MSDN.

                Генерировать прокси-классы из проекта клиентского приложения Visual Studio

                Чтобы сгенерировать прокси-классы из проекта клиентского приложения Visual Studio:

                1. В контекстном меню проекта клиентского приложения Visual Studio, в котором планируется реализация интеграции с Creatio, выберите пункт Add Service Reference… .
                2. В поле Address введите полный адрес сервиса EntityDataService.svc .
                3. Нажмите на кнопку Go и укажите имя и пароль пользователя Creatio. Если аутентификация прошла успешно, то в окне Services отобразятся поддерживаемые сервисом сущности.
                4. В поле Namespace укажите имя пространства имен, в котором расположены сгенерированные прокси-классы (например, CreatioServiceReference ). Ссылку на это пространство имен в дальнейшем добавьте в блок using кода проекта.
                5. Для генерации прокси-классов нажмите кнопку ОК . При этом в проект добавляется новый файл кода Reference.cs , содержащий описание прокси-классов, которые доступны к использованию для обращения и взаимодействия с ресурсами сервиса данных как с объектами.

                Visual Studio предоставляет возможность генерации прокси-классы сервиса из сохраненного на диске файла метаданных сервиса. Для этого на шаге 2 в поле Address введите полный путь к файлу метаданных с префиксом file:// .

                file://C:/metadata.xml

                После генерации прокси-классов сервиса в проект добавляется ссылка на сборку Microsoft.Data.Services.Client.dll , которая реализует поддержку протокола OData 3. Если в клиентском приложении необходимо использовать протокол более ранней версии, то ссылку на соответствующую сборку добавьте вручную. Данная клиентская библиотека позволяет выполнять запросы к сервису данных EntityDataService.svc , используя стандартные шаблоны программирования .NET Framework, включая использование языка запросов LINQ.

                Чтобы успешно компилировать проект:

                  В код проекта добавьте директивы using .

                Директивы using

                using System; using System.Data.Services.Client; using System.Net; using Terrasoft.Sdk.Examples.CreatioServiceReference; using System.Linq;

                Объявление переменной адреса сервиса OData

                private static Uri serverUri = new Uri("http:////0/ServiceModel/EntityDataService.svc/");

                Особенности использования протокола OData

                Особенности, которые необходимо учитывать при использовании протокола OData:

                • Невозможно создать системных пользователей.
                • Невозможно задать культуру возвращаемых данных. Культура определяется культурой пользователя от имени которого выполняется запрос.
                • Тело ответа на запрос может содержать максимум 20 000 строк.
                • Пакетный запрос может содержать максимум 100 подзапросов.
                • Максимальный размер файла, который можно загрузить с помощью запроса, задается системной настройкой Максимальный размер загружаемого файла ( Attachment max size , код MaxFileSize ) (по умолчанию — 10 Мб).

                Решение типичных ошибок при интеграции по протоколу OData

                При выполнении запросов по протоколу OData могут возникать ошибки, которые представлены в таблице ниже.

                Типичные ошибки при интеграции по протоколу OData

                Коды ошибок, которые возвращает Creatio в ответ на запрос по протоколу OData 4, описаны в статье Веб-сервис odata (OData 4).

                Смотрите также
                Онлайн-курсы
                Примеры интеграций по OData

                Creatio API документация, которая содержит примеры различных CRUD-операций к Creatio с использованием протоколов OData 3 и OData 4, доступна на сайте Postman.

                Примеры запросов с типом данных Stream

                Элементы с типом данных Stream:

                • Изображения.
                • Файлы.
                • Двоичные данные.

                Для работы с типом данных Stream используются стандартные методы:

                • GET — получение данных.
                • POST — добавление данных.
                • PUT — изменение данных.
                • DELETE — удаление данных.

                Для отображения результата выполнения запросов к Creatio при работе с типом данных Stream необходимо очистить кэш браузера.

                Получить данные

                Пример. Используя сервис работы с данными OData, получить фото контакта «New user».

                Реализация примера

                1. Получите идентификатор фото контакта «New user». Фото контакта содержится в колонке [Data] таблицы [SysImage] базы данных. Чтобы получить идентификатор фото контакта «New user», выполните следующий SQL-запрос.
                select Id from SysImage where PhotoId from Contact where Name = 'New user')
                29FE7EDF-4DB9-4E09-92B0-018047BA1F71
                // Получить значение поля [Data] экземпляра объекта с [Id] 29FE7EDF-4DB9-4E09-92B0-018047BA1F71 коллекции [SysImage]. GET http://mycreatio.com/0/odata/SysImage(29FE7EDF-4DB9-4E09-92B0-018047BA1F71)/Data
                Status: 200 OK 

                scr_ContactPhoto.png

                scr_GetImage.png

                Добавить данные

                Пример. Используя сервис работы с данными OData, добавить контакт «New user». Затем добавить контакту фото.

                scr_NewContactPhoto.png

                Реализация примера

                1. Добавьте контакт «New user». Все контакты содержатся в таблице [Contact] базы данных. Чтобы добавить контакт «New user», выполните следующий запрос.
                // Добавить экземпляр объекта коллекции [Contact]. POST http://mycreatio.com/0/odata/Contact Accept: application/json; odata=verbose Content-Type: application/json; odata=verbose; IEEE754Compatible=true BPMCSRF: OpK/NuJJ1w/SQxmPvwNvfO < // В поле [Name] записать имя контакта "New user". "Name": "New user" >
                Status: 201 Created < "@odata.context": "http://mycreatio.com/0/odata/$metadata#Contact/$entity", "Id": "4c63c8fa-467b-48a6-973f-b2069298404f", "Name": "New user", "OwnerId": "410006e1-ca4e-4502-a9ec-e54d922d2c00", "CreatedOn": "2021-01-14T08:33:29.009023Z", "CreatedById": "410006e1-ca4e-4502-a9ec-e54d922d2c00", "ModifiedOn": "2021-01-14T08:33:29.009023Z", "ModifiedById": "410006e1-ca4e-4502-a9ec-e54d922d2c00", "ProcessListeners": 0, "Dear": "", "SalutationTypeId": "00000000-0000-0000-0000-000000000000", "GenderId": "00000000-0000-0000-0000-000000000000", "AccountId": "00000000-0000-0000-0000-000000000000", "DecisionRoleId": "00000000-0000-0000-0000-000000000000", "TypeId": "00000000-0000-0000-0000-000000000000", "JobId": "00000000-0000-0000-0000-000000000000", "JobTitle": "", "DepartmentId": "00000000-0000-0000-0000-000000000000", "BirthDate": "0001-01-01T00:00:00Z", "Phone": "", "MobilePhone": "", "HomePhone": "", "Skype": "", "Email": "", "AddressTypeId": "00000000-0000-0000-0000-000000000000", "Address": "", "CityId": "00000000-0000-0000-0000-000000000000", "RegionId": "00000000-0000-0000-0000-000000000000", "Zip": "", "CountryId": "00000000-0000-0000-0000-000000000000", "DoNotUseEmail": false, "DoNotUseCall": false, "DoNotUseFax": false, "DoNotUseSms": false, "DoNotUseMail": false, "Notes": "", "Facebook": "", "LinkedIn": "", "Twitter": "", "FacebookId": "", "LinkedInId": "", "TwitterId": "", "ContactPhoto@odata.mediaEditLink": "Contact(4c63c8fa-467b-48a6-973f-b2069298404f)/ContactPhoto", "ContactPhoto@odata.mediaReadLink": "Contact(4c63c8fa-467b-48a6-973f-b2069298404f)/ContactPhoto", "ContactPhoto@odata.mediaContentType": "application/octet-stream", "TwitterAFDAId": "00000000-0000-0000-0000-000000000000", "FacebookAFDAId": "00000000-0000-0000-0000-000000000000", "LinkedInAFDAId": "00000000-0000-0000-0000-000000000000", "PhotoId": "00000000-0000-0000-0000-000000000000", "GPSN": "", "GPSE": "", "Surname": "user", "GivenName": "New", "MiddleName": "", "Confirmed": true, "IsNonActualEmail": false, "Completeness": 0, "LanguageId": "6ebc31fa-ee6c-48e9-81bf-8003ac03b019", "Age": 0 >

                scr_CreateUser.png

                // Добавить экземпляр объекта коллекции [SysImage]. POST http://mycreatio.com/0/odata/SysImage Accept: application/json; odata=verbose Content-Type: application/json; odata=verbose; IEEE754Compatible=true BPMCSRF: OpK/NuJJ1w/SQxmPvwNvfO < // В поле [Name] записать название файла с фото контакта. "Name": "scr_NewContactPhoto.png", // В поле [Id] записать произвольный идентификатор записи в таблице [SysImage]. "Id": "410006E1-CA4E-4502-A9EC-E54D922D2C01", // В поле [MimeType] записать тип файла с фото контакта. "MimeType": "image/png" >
                Status: 201 Created < "@odata.context": "http://mycreatio.com/0/odata/$metadata#SysImage/$entity", "Id": "410006e1-ca4e-4502-a9ec-e54d922d2c01", "CreatedOn": "2021-01-14T08:52:47.7573789Z", "CreatedById": "410006e1-ca4e-4502-a9ec-e54d922d2c00", "ModifiedOn": "2021-01-14T08:52:47.7573789Z", "ModifiedById": "410006e1-ca4e-4502-a9ec-e54d922d2c00", "ProcessListeners": 0, "UploadedOn": "0001-01-01T00:00:00Z", "Name": "scr_NewContactPhoto.png", "Data@odata.mediaEditLink": "SysImage(410006e1-ca4e-4502-a9ec-e54d922d2c01)/Data", "Data@odata.mediaReadLink": "SysImage(410006e1-ca4e-4502-a9ec-e54d922d2c01)/Data", "Data@odata.mediaContentType": "application/octet-stream", "MimeType": "image/png", "HasRef": false, "PreviewData@odata.mediaEditLink": "SysImage(410006e1-ca4e-4502-a9ec-e54d922d2c01)/PreviewData", "PreviewData@odata.mediaReadLink": "SysImage(410006e1-ca4e-4502-a9ec-e54d922d2c01)/PreviewData", "PreviewData@odata.mediaContentType": "application/octet-stream" >

                В таблицу [SysImage] базы данных была добавлена запись, но колонка [Data] содержит значение «0х». Изображение необходимо передать в теле запроса, а название изображения должно совпадать из значением поля [Name] . Чтобы добавить фото контакта в колонку [Data] , выполните следующий запрос.

                // Изменить значение поля [Data] экземпляра объекта с [Id] 410006e1-ca4e-4502-a9ec-e54d922d2c01 коллекции [SysImage]. PUT http://mycreatio.com/0/odata/SysImage(410006e1-ca4e-4502-a9ec-e54d922d2c01)/Data Accept: application/json; text/plain; */* Content-Type: application/octet-stream; IEEE754Compatible=true BPMCSRF: OpK/NuJJ1w/SQxmPvwNvfO

                scr_NewContactPhoto.png

                Status: 200 OK 
                // Изменить поле [PhotoId] экземпляра объекта с [Id] 4c63c8fa-467b-48a6-973f-b2069298404f коллекции [Contact]. PATCH http://mycreatio.com/0/odata/Contact(4c63c8fa-467b-48a6-973f-b2069298404f) Accept: application/json;odata=verbose Content-Type: application/json; odata=verbose; IEEE754Compatible=true BPMCSRF: OpK/NuJJ1w/SQxmPvwNvfO < // В поле [PhotoId] записать идентификатор записи в таблице [SysImage]. "PhotoId": "410006e1-ca4e-4502-a9ec-e54d922d2c01" >
                Status: 204 No Content 

                scr_AddImage.png

                Чтобы добавить фото существующему контакту выполните:

                1. POST -запрос на добавление экземпляра объекта коллекции [SysImage] .
                2. PUT -запрос на изменение значения поля [Data] экземпляра объекта коллекции [SysImage] .
                3. PATCH -запрос на выполнение привязку добавленного фото к контакту «New user».

                Изменить данные

                Пример. Используя сервис работы с данными OData, изменить фото существующего контакта «New user».

                scr_NewContactPhoto.png

                Реализация примера

                1. Получите идентификатор фото контакта «New user». Фото контакта содержится в колонке [Data] таблицы [SysImage] базы данных. Чтобы получить идентификатор фото контакта «New user», выполните следующий SQL-запрос.
                select Id from SysImage where PhotoId from Contact where Name = 'New user')
                29FE7EDF-4DB9-4E09-92B0-018047BA1F71
                // Изменить поле [Data] экземпляра объекта с [Id] 29FE7EDF-4DB9-4E09-92B0-018047BA1F71 коллекции [SysImage]. PUT http://mycreatio.com/0/odata/SysImage(29FE7EDF-4DB9-4E09-92B0-018047BA1F71)/Data Accept: application/json; text/plain; */* Content-Type: application/octet-stream; IEEE754Compatible=true BPMCSRF: OpK/NuJJ1w/SQxmPvwNvfO

                scr_NewContactPhoto.png

                Status: 200 OK 

                scr_PutImage.png

                Удалить данные

                Пример. Используя сервис работы с данными OData, удалить фото контакта «New user».

                Реализация примера

                1. Получите идентификатор фото контакта «New user». Фото контакта содержится в колонке [Data] таблицы [SysImage] базы данных. Чтобы получить идентификатор фото контакта «New user», выполните следующий SQL-запрос.
                select Id from SysImage where PhotoId from Contact where Name = 'New user')
                29FE7EDF-4DB9-4E09-92B0-018047BA1F71
                // Удалить значение поля [Data] экземпляра объекта с [Id] 29FE7EDF-4DB9-4E09-92B0-018047BA1F71 коллекции [SysImage]. DELETE http://mycreatio.com/0/odata/SysImage(29FE7EDF-4DB9-4E09-92B0-018047BA1F71)/Data Accept: application/json; text/plain; */* Content-Type: application/json; charset=utf-8; IEEE754Compatible=true BPMCSRF: OpK/NuJJ1w/SQxmPvwNvfO
                Status: 204 No Content 

                scr_DeleteImage.png

                Примеры пакетных запросов

                Пакетный запрос (batch-запрос) позволяет объединить множество HTTP-запросов в один, указав в теле каждый запрос как отдельный объект. Сервер баз данных Creatio возвращает один HTTP-ответ, внутри которого содержатся ответы на каждый переданный запрос. Использование пакетных запросов позволяет повысить производительность приложения.

                Для пакетных запросов используются:

                • HTTP-метод POST .
                • Параметр $batch.
                • Заголовок Content-Type .

                Значения заголовка Content-Type :

                • application/json — позволяет установить единый тип возвращаемого сервером контента для всех запросов пакетного запроса.
                • multipart/mixed — позволяет в теле пакетного запроса установить свой заголовок Content-Type для каждого запроса.

                Если один из запросов завершается с кодом ответа групп 4хх-5хх, то прерывается выполнение последующих запросов. Чтобы после неуспешного выполнения запроса продолжить выполнение следующих запросов, необходимо к основному HTTP-запросу добавить заголовок Prefer: continue-on-error .

                Важно. Максимальное количество запросов в пакетном запросе — 100.

                Пакетный запрос ( Content-Type: application/json )

                POST http://mycreatio.com/0/odata/$batch Content-Type: application/json; odata=verbose; IEEE754Compatible=true Accept: application/json BPMCSRF: OpK/NuJJ1w/SQxmPvwNvfO ForceUseSession: true < "requests": [ < // Добавить экземпляр объекта коллекции City. "method": "POST", "url": "Сity", "id": "t3", "body": < // Добавить в поле Name значение Burbank. "Name": "Burbank" >, "headers": < "Content-Type": "application/json;odata=verbose", "Accept": "application/json;odata=verbose", "Prefer": "continue-on-error" >>, < // Добавить экземпляр объекта коллекции Сity. "method": "POST", "atomicityGroup": "g1", "url": "Сity", "id": "t3", "body": < // Добавить в поле Id значение 62f9bc01-57cf-4cc7-90bf-8672acc922e3. "Id": "62f9bc01-57cf-4cc7-90bf-8672acc922e3", // Добавить в поле Name значение Spokane. "Name": "Spokane" >, "headers": < "Content-Type": "application/json;odata=verbose", "Accept": "application/json;odata=verbose", "Prefer": "continue-on-error" >>, < // Изменить экземпляр объекта коллекции City с идентификатором 62f9bc01-57cf-4cc7-90bf-8672acc922e3. "method": "PATCH", "atomicityGroup": "g1", "url": "City/62f9bc01-57cf-4cc7-90bf-8672acc922e3", "id": "t2", "body": < // Изменить значение поля Name на Texas. "Name": "Texas" >, "headers": < "Content-Type": "application/json;odata=verbose", "Accept": "application/json;odata=verbose", "Prefer": "continue-on-error" >> ] >
                Status: 200 OK < "responses": [ < "id": "t3", "status": 201, "headers": < "location": "https://mycreatio.com/0/odata/City(b6a05348-55b1-4314-a228-436ba305d2f3)", "content-type": "application/json; odata.metadata=minimal", "odata-version": "4.0" >, "body": < "@odata.context": "https://mycreatio.com/0/odata/$metadata#City/$entity", "Id": "b6a05348-55b1-4314-a228-436ba305d2f3", "CreatedOn": "2020-05-18T17:50:39.2838673Z", "CreatedById": "dad159f3-6c2d-446a-98d2-0f4d26662bbe", "ModifiedOn": "2020-05-18T17:50:39.2838673Z", "ModifiedById": "dad159f3-6c2d-446a-98d2-0f4d26662bbe", "Name": "Burbank", "Description": "", "CountryId": "00000000-0000-0000-0000-000000000000", "RegionId": "00000000-0000-0000-0000-000000000000", "TimeZoneId": "00000000-0000-0000-0000-000000000000", "ProcessListeners": 0 >>, < "id": "t3", "atomicityGroup": "c59e36b2-2aa9-44fa-86d3-e7d68eecbfa0", "status": 201, "headers": < "location": "https://mycreatio.com/0/odata/City(62f9bc01-57cf-4cc7-90bf-8672acc922e3)", "content-type": "application/json; odata.metadata=minimal", "odata-version": "4.0" >, "body": < "@odata.context": "https://mycreatio.com/0/odata/$metadata#City/$entity", "Id": "62f9bc01-57cf-4cc7-90bf-8672acc922e3", "CreatedOn": "2020-05-18T17:50:39.361994Z", "CreatedById": "dad159f3-6c2d-446a-98d2-0f4d26662bbe", "ModifiedOn": "2020-05-18T17:50:39.361994Z", "ModifiedById": "dad159f3-6c2d-446a-98d2-0f4d26662bbe", "Name": "Spokane", "Description": "", "CountryId": "00000000-0000-0000-0000-000000000000", "RegionId": "00000000-0000-0000-0000-000000000000", "TimeZoneId": "00000000-0000-0000-0000-000000000000", "ProcessListeners": 0 >>, < "id": "t2", "atomicityGroup": "c59e36b2-2aa9-44fa-86d3-e7d68eecbfa0", "status": 204, "headers": < "odata-version": "4.0" >> ] >

                Пакетный запрос ( Content-Type: application/json и Prefer: continue-on-error )

                POST http://mycreatio.com/0/odata/$batch Content-Type: application/json; odata=verbose; IEEE754Compatible=true Accept: application/json BPMCSRF: OpK/NuJJ1w/SQxmPvwNvfO ForceUseSession: true Prefer: continue-on-error < "requests": [ < // Добавить экземпляр объекта коллекции City. "method": "POST", "url": "City", "id": "t3", "body": < // Добавить в поле Name значение Burbank. "Name": "Burbank" >, "headers": < "Content-Type": "application/json;odata=verbose", "Accept": "application/json;odata=verbose", "Prefer": "continue-on-error" >>, < // Изменить экземпляр объекта коллекции City с идентификатором 62f9bc01-57cf-4cc7-90bf-8672acc922e2. "method": "PATCH", "atomicityGroup": "g1", "url": "City/62f9bc01-57cf-4cc7-90bf-8672acc922e2", "id": "t2", "body": < // Изменить значение поля Name на Indiana. "Name": "Indiana" >, "headers": < "Content-Type": "application/json;odata=verbose", "Accept": "application/json;odata=verbose", "Prefer": "continue-on-error" >>, < // Добавить экземпляр объекта коллекции City. "method": "POST", "atomicityGroup": "g1", "url": "City", "id": "t3", "body": < // Добавить в поле Id значение 62f9bc01-57cf-4cc7-90bf-8672acc922a1. "Id": "62f9bc01-57cf-4cc7-90bf-8672acc922a1", // Добавить в поле Name значение Iowa. "Name": "Iowa" >, "headers": < "Content-Type": "application/json;odata=verbose", "Accept": "application/json;odata=verbose", "Prefer": "continue-on-error" >> ] >
                Status: 200 OK < "responses": [ < "id": "t3", "status": 201, "headers": < "location": "https://mycreatio.com/0/odata/City(2f5e68f8-38bd-43c1-8e15-a2f13b0aa56a)", "content-type": "application/json; odata.metadata=minimal", "odata-version": "4.0" >, "body": < "@odata.context": "https://mycreatio.com/0/odata/$metadata#City/$entity", "Id": "2f5e68f8-38bd-43c1-8e15-a2f13b0aa56a", "CreatedOn": "2020-05-18T18:06:50.7329808Z", "CreatedById": "dad159f3-6c2d-446a-98d2-0f4d26662bbe", "ModifiedOn": "2020-05-18T18:06:50.7329808Z", "ModifiedById": "dad159f3-6c2d-446a-98d2-0f4d26662bbe", "Name": "Burbank", "Description": "", "CountryId": "00000000-0000-0000-0000-000000000000", "RegionId": "00000000-0000-0000-0000-000000000000", "TimeZoneId": "00000000-0000-0000-0000-000000000000", "ProcessListeners": 0 >>, < "id": "t2", "atomicityGroup": "0c1c4019-b9fb-4fb3-8642-2d0660c4551a", "status": 204, "headers": < "odata-version": "4.0" >>, < "id": "t3", "atomicityGroup": "0c1c4019-b9fb-4fb3-8642-2d0660c4551a", "status": 201, "headers": < "location": "https://mycreatio.com/0/odata/City(62f9bc01-57cf-4cc7-90bf-8672acc922a1)", "content-type": "application/json; odata.metadata=minimal", "odata-version": "4.0" >, "body": < "@odata.context": "https://mycreatio.com/0/odata/$metadata#City/$entity", "Id": "62f9bc01-57cf-4cc7-90bf-8672acc922a1", "CreatedOn": "2020-05-18T18:06:50.7954775Z", "CreatedById": "dad159f3-6c2d-446a-98d2-0f4d26662bbe", "ModifiedOn": "2020-05-18T18:06:50.7954775Z", "ModifiedById": "dad159f3-6c2d-446a-98d2-0f4d26662bbe", "Name": "Iowa", "Description": "", "CountryId": "00000000-0000-0000-0000-000000000000", "RegionId": "00000000-0000-0000-0000-000000000000", "TimeZoneId": "00000000-0000-0000-0000-000000000000", "ProcessListeners": 0 >> ] >

                Пакетный запрос ( Content-Type: multipart/mixed )

                POST http://mycreatio.com/0/odata/$batch Content-Type: multipart/mixed;boundary=batch_a685-9724-d873; IEEE754Compatible=true BPMCSRF: OpK/NuJJ1w/SQxmPvwNvfO ForceUseSession: true --batch_a685-9724-d873 Content-Type: multipart/mixed; boundary=changeset_06da-d998-8e7e --changeset_06da-d998-8e7e Content-Type: application/http Content-Transfer-Encoding: binary // Добавить экземпляр объекта коллекции City. POST City HTTP/1.1 Content-ID: 1 Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1 Content-Type: application/json;odata=verbose // Добавить в поле Name значение Gilbert. --changeset_06da-d998-8e7e Content-Type: application/http Content-Transfer-Encoding: binary // Изменить экземпляр объекта коллекции City с идентификатором 62f9bc01-57cf-4cc7-90bf-8672acc922e2. PATCH City/62f9bc01-57cf-4cc7-90bf-8672acc922e2 HTTP/1.1 Content-ID: 2 Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1 Content-Type: application/json;odata=verbose // Изменить значение поля Name на Lincoln. --changeset_06da-d998-8e7e Content-Type: application/http Content-Transfer-Encoding: binary // Удалить экземпляр объекта коллекции City с идентификатором 62f9bc01-57cf-4cc7-90bf-8672acc922e2. DELETE City/62f9bc01-57cf-4cc7-90bf-8672acc922e2 HTTP/1.1 Content-ID: 3 Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1 Content-Type: application/json;odata=verbose
                Status: 200 OK --batchresponse_e17aace9-5cbb-49bd-b7ad-f1be8cc8c9d8 Content-Type: multipart/mixed; boundary=changesetresponse_a08c1df6-4b82-4a9b-be61-7ef4cc7b23ba --changesetresponse_a08c1df6-4b82-4a9b-be61-7ef4cc7b23ba Content-Type: application/http Content-Transfer-Encoding: binary Content-ID: 1 HTTP/1.1 201 Created Location: https://mycreatio.com/0/odata/City(fbd0565f-fa8a-4214-ae89-c976c5f3acb4) Content-Type: application/json; odata.metadata=minimal OData-Version: 4.0 < "@odata.context": "https://mycreatio.com/0/odata/$metadata#City/$entity", "Id": "fbd0565f-fa8a-4214-ae89-c976c5f3acb4", "CreatedOn": "2020-05-18T18:41:57.0917235Z", "CreatedById": "dad159f3-6c2d-446a-98d2-0f4d26662bbe", "ModifiedOn": "2020-05-18T18:41:57.0917235Z", "ModifiedById": "dad159f3-6c2d-446a-98d2-0f4d26662bbe", "Name": "Gilbert", "Description": "", "CountryId": "00000000-0000-0000-0000-000000000000", "RegionId": "00000000-0000-0000-0000-000000000000", "TimeZoneId": "00000000-0000-0000-0000-000000000000", "ProcessListeners": 0 >--changesetresponse_a08c1df6-4b82-4a9b-be61-7ef4cc7b23ba Content-Type: application/http Content-Transfer-Encoding: binary Content-ID: 2 HTTP/1.1 204 No Content OData-Version: 4.0 --changesetresponse_a08c1df6-4b82-4a9b-be61-7ef4cc7b23ba Content-Type: application/http Content-Transfer-Encoding: binary Content-ID: 3 HTTP/1.1 204 No Content --changesetresponse_a08c1df6-4b82-4a9b-be61-7ef4cc7b23ba-- --batchresponse_e17aace9-5cbb-49bd-b7ad-f1be8cc8c9d8--

                Пакетный запрос ( Content-Type: multipart/mixed и разными наборами запросов)

                POST http://mycreatio.com/0/odata/$batch Content-Type: multipart/mixed;boundary=batch_a685-9724-d873; IEEE754Compatible=true Accept: application/json BPMCSRF: OpK/NuJJ1w/SQxmPvwNvfO ForceUseSession: true —batch_a685-9724-d873 Content-Type: multipart/mixed; boundary=changeset_06da-d998-8e7e —changeset_06da-d998-8e7e Content-Type: application/http Content-Transfer-Encoding: binary // Добавить экземпляр объекта коллекции City. POST City HTTP/1.1 Content-ID: 1 Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1 Content-Type: application/json;odata=verbose // Добавить в поле Id значение d6bc67b1-9943-4e47-9aaf-91bf83e9c285. // Добавить в поле Name значение Nebraska. —batch_a685-9724-d873 Content-Type: multipart/mixed; boundary=changeset_06da-d998-8e71 —changeset_06da-d998-8e71 Content-Type: application/http Content-Transfer-Encoding: binary // Добавить экземпляр объекта коллекции City. POST City HTTP/1.1 Content-ID: 2 Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1 Content-Type: application/json;odata=verbose // Добавить в поле Id значение d6bc67b1-9943-4e47-9aaf-91bf83e9c286. // Добавить в поле Name значение Durham.

                Status: 200 OK < "responses": [ < "id": "1", "atomicityGroup": "e9621f72-42bd-47c1-b271-1027e4b68e3b", "status": 201, "headers": < "location": "https://mycreatio.com/0/odata/City(d6bc67b1-9943-4e47-9aaf-91bf83e9c285)", "content-type": "application/json; odata.metadata=minimal", "odata-version": "4.0" >, "body": < "@odata.context": "https://mycreatio.com/0/odata/$metadata#City/$entity", "Id": "d6bc67b1-9943-4e47-9aaf-91bf83e9c285", "CreatedOn": "2020-05-18T18:49:16.3766324Z", "CreatedById": "dad159f3-6c2d-446a-98d2-0f4d26662bbe", "ModifiedOn": "2020-05-18T18:49:16.3766324Z", "ModifiedById": "dad159f3-6c2d-446a-98d2-0f4d26662bbe", "Name": "Nebraska", "Description": "", "CountryId": "00000000-0000-0000-0000-000000000000", "RegionId": "00000000-0000-0000-0000-000000000000", "TimeZoneId": "00000000-0000-0000-0000-000000000000", "ProcessListeners": 0 >>, < "id": "2", "atomicityGroup": "960e2272-d8cb-4b4d-827c-0181485dd71d", "status": 201, "headers": < "location": "https://mycreatio.com/0/odata/City(d6bc67b1-9943-4e47-9aaf-91bf83e9c286)", "content-type": "application/json; odata.metadata=minimal", "odata-version": "4.0" >, "body": < "@odata.context": "https://mycreatio.com/0/odata/$metadata#City/$entity", "Id": "d6bc67b1-9943-4e47-9aaf-91bf83e9c286", "CreatedOn": "2020-05-18T18:49:16.4078852Z", "CreatedById": "dad159f3-6c2d-446a-98d2-0f4d26662bbe", "ModifiedOn": "2020-05-18T18:49:16.4078852Z", "ModifiedById": "dad159f3-6c2d-446a-98d2-0f4d26662bbe", "Name": "Durham", "Description": "", "CountryId": "00000000-0000-0000-0000-000000000000", "RegionId": "00000000-0000-0000-0000-000000000000", "TimeZoneId": "00000000-0000-0000-0000-000000000000", "ProcessListeners": 0 >> ] >

                OData — the best way to REST

                Home

                An open protocol to allow the creation and consumption of queryable and interoperable RESTful APIs in a simple and standard way.

                Blog

                Recent Posts

                OData 4.01 Committee Spec Approved

                By Michael Pizzo

                Whats New in REST APIs Seminar December 5 2017

                By Sumit Sarkar

                Visual Studio Code Knows OData

                By Michael Pizzo

                OData Published as an ISO Standard

                By Michael Pizzo

                OData (Open Data Protocol) is an ISO/IEC approved, OASIS standard that defines a set of best practices for building and consuming RESTful APIs. OData helps you focus on your business logic while building RESTful APIs without having to worry about the various approaches to define request and response headers, status codes, HTTP methods, URL conventions, media types, payload formats, query options, etc. OData also provides guidance for tracking changes, defining functions/actions for reusable procedures, and sending asynchronous/batch requests.

                OData RESTful APIs are easy to consume. The OData metadata, a machine-readable description of the data model of the APIs, enables the creation of powerful generic client proxies and tools.

                Tools

                Visual Studio Code for OData

                OData for Visual Studio Code is a Visual Studio Code extension that adds rich support for the OData query language

                XOData

                XOData is a generic online OData API/Service visualizer and explorer. It assists in rapid prototyping, verification, testing, and documentation of OData APIs. With XOData Chrome App it’s also possible to explore OData Services deployed locally or on private networks.

                Resources

                Getting Started

                Getting Started

                To get started, take a look at Understanding OData in 6 steps. And then the Basic Tutorial, Advanced Tutorial and Postman Tutorial will provide practical samples to learn OData.

                Управление данными с помощью протокола OData

                Open Data Protocol (OData) – это открытый веб-протокол для запроса и обновления данных. Протокол позволяет выполнять операции с ресурсами, используя в качестве запросов HTTP-команды, и обмениваться данными в форматах JSON или XML.

                OData является одним из лучших стандартов для создания RESTful API.

                Вы можете запрашивать данные используя простые HTTP запросы, например:

                OData позволяет задавать огромное число параметров, которые позволяют сформировать очень сложные запросы к источнику данных, например:

                https://samples.databoom.space/api1/sampledb/collections/books?$filter=publisher/president/likes/author/firstname eq ‘Georgie’&$top=10&$orderby=title
                Выбрать все книги, удовлетворяющие следующему условию: президент издательства в котором издана книга, любит книги некоего автора с именем “Georgie”. Результат запроса необходимо отсортировать по названию, выдать первые 10 книг.

                Язык запросов OData сопоставим по мощности с SQL.

                Базовые возможности OData
                • Простое чтение данных (запросы без параметров)
                  • Получение коллекции объектов
                  • Получение отдельного объекта
                  • Получение отдельного свойства
                  • Получение объектов по связям. Например, получение списка друзей друзей.
                  • Поиск по критериям (“меньше”, ”больше” и т.п.), возможность построения сложных условий, используя логические выражения.
                  • Поиск по связям (по связанным объектам)
                  • Сортировка по любому набору полей
                  • Получение составных сложных объектов, например, получить данные о человеке вместе с его телефонами и списком друзей
                  • Пэйджинг
                  • Добавление простых объектов
                  • Добавление коллекций объектов
                  • Добавление составных объектов (вместе с вложенными объектами)
                  • Модификация отдельных свойств (полей)
                  • Замена объекта целиком на новый
                  • Удаление объектов
                  • Удаление коллекций
                  • Удаление отдельных свойств (полей)
                  Библиотеки для работы с OData

                  В настоящее время существует большое количество библиотек, поддерживающих протокол OData, и каждый день появляются новые.
                  В частности, с OData работают такие JavaScript библиотеки, как Kendo UI, DevExtreme Web, Syncfusion HTML5 controls, Infragistics HTML5 controls, OpenUI5, Wijmo, JayData, Breeze.js, datajs, ODataJS, angular-odata, и т.д. Существуют также библиотеки для Java, .NET, C++, Python, Objective-C и т.д.

                  Многие из этих библиотек существенно упрощают разработку сложных приложений благодаря стандарту OData. Например, достаточно грид контролу указать URL к серверу OData и все остальное он сделает сам: пэйджинг, сортировку, добавление- модификацию-удаление записей, фильтрацию данных, группировку и т.д.

                  NitrosBase.js – готовый OData сервер

                  NitrosBase.js – это готовый к употреблению OData сервер. Он дает возможность создать базу данных, добавить произвольные JSON объекты без описания схемы данных, и делать OData запросы для получения и модификации данных.

                  Классический сценарий использования NitrosBase.js – это быстрая разработка прототипов приложений, работающих с OData сервером. При разработке прототипа Вы можете просто положить необходимые контролы на форму, и они сразу же работают без создания серверных кодов. Если Вы добавляете, удаляете поля в JavaScript объектах, модифицирует связи между объектами Вам не придется менять схему базы данных и модифицировать серверные коды. В тоже время он позволяет выполнять запросы любой сложности.

                  Разработав живой прототип приложения Вы получаете полную спецификацию Вашего API и устоявшуюся схему данных. Теперь Вы можете приступить к разработке сервера или оставить NitrosBase.js

                  NitrosBase.js – это наш новый проект (http://databoom.space) и мы хотели бы услышать рекомендации сообщества по улучшению и развитию проекта.

                  • Блог компании databoom
                  • Веб-разработка
                  • JavaScript
                  • Программирование

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *