Как POST-объект OData и связать его с несколькими существующими объектами одновременно? - PullRequest
1 голос
/ 15 апреля 2020

Как опубликовать сущность в конечной точке OData, одновременно связывая ее с другими существующими сущностями в теле?


Рассмотрим следующую структуру класса (образец):

class Invoice
{
    public int Id { get; set; }

    public Person Issuer { get; set; }

    public Person Recipient { get; set; }

    // other properties
}

class Person
{
    public int Id { get; set; }

    // other properties
}

И Invoice, и Person являются сущностями в моем домене (таким образом, свойство Id). Представьте, что оба экспонируются в своих собственных наборах сущностей, поэтому:

  • GET http://host/odata/People(1)

    возвращает Person с Id = 1

  • GET http://host/odata/Invoices(2)?$expand='Issuer, Recipient'

    возвращает Invoice с Id = 2 и расширениями Issuer и Recipient в полезной нагрузке

Теперь рассмотрим следующее требование :

Я хочу создать в системе новый счет, который будет связан с существующим эмитентом и получателем

Как мне "сообщить" платформе OData, что я Хотите связать данное свойство навигации с существующим объектом? Как бы моё действие контроллера было уведомлено, что это намерение?

В идеале, я бы хотел, чтобы тело POST выглядело так:

  • POST http://host/odata/Invoices

    {"Issuer": "/ odata / People (1)", "Recipient": "/ odata / People (2)", "Property1": "someValue", "Property2": "100",. ..}

Как только сервер получит эту полезную нагрузку, он должен:

  1. Загрузить необходимые "people (1)" Person для Issuer имущество. Если он не существует, должен быть возвращен неверный запрос.
  2. Загрузите необходимые "people (2)" Person для свойства Recipient. Если он не существует, должен быть возвращен неверный запрос.
  3. Создайте новый Invoice экземпляр и назначьте Issuer и Recipient сверху, а затем сохраните его в базе данных.

Я знаю, что OData имеет поддержку для последующей настройки отношений со специальными URL-адресами PUT / POST с использованием синтаксиса entity/relation/$ref. С таким синтаксисом я мог бы сделать что-то вроде этого:

  1. POST http://host/odata/Invoices

    { "Property1": "someValue", "Property2": "100" }

  2. PUT http://host/odata/Invoices(x)/Issuer/$ref

    {"@odata.id":"http://host/odata/People(1)"}

  3. PUT http://host/odata/Invoices(x)/Recipient/$ref

    {"@odata.id":"http://host/odata/People(2)"}

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

Я попробовал несколько идей, чтобы увидеть, что сервер примет, и это, казалось, go через:

{
    "Issuer": { "@odata.id": "/odata/People(1)" },
    "Recipient": { "@odata.id": "/odata/People(2)" },
    "Property1": "someValue",
    "Property2": "100",
    ...
}

Но я понятия не имею, как я смогу читать / анализировать идентификаторы из этого (например, как это делается в выделенном методе Ref), или даже если это поддерживается в стандарт OData.

Сейчас я прибегну к простой передаче свойства ID в модели и на сервере, предполагая, что это всегда будет означать существующие отношения, но это далеко от идеала, поскольку это не так. достаточно универсальный и сделает мой API негибким.

...