Следует ввести объекты переноса данных для конечных точек RESTful соответствовать выходной объекты переноса данных?


Я работаю над RESTful API, и у меня возникли некоторые проблемы с тем, чтобы разобраться в процедуре подачи входных данных в API.

Допустим, у меня есть ресурс "Person", который можно извлечь следующим образом: api/person/{id} и возвращает объект, подобный этому:

public class Person
{
    public int Id { get; set; }
    public string Surname { get; set; }
    public string GivenName { get; set; }
    public DateTime DateOfBirth { get; set; }
}

Если я хочу обновить этого человека, должен ли API ожидать полный экземпляр Person, или допустимо использовать отдельный DTO?

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

public class UpdatePersonDto
{
    public string Surname { get; set; }
    public string GivenName { get; set; }
}

Это будет означать, что я буду иметь эту конечную точку api/person/{id}, возвращающую Person при использовании GET, Принимая в качестве входных данных UpdatePersonDto при использовании PUT. Это звучит неправильно для меня, но я не уверен, что я просто параноик.

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

2 5

2 ответа:

Похоже, что все остальные единодушны в том, что при обновлении с использованием PUT один поставляет всю сущность для замены.

Программно, это будет работать, поставив /person / {id} принимающий вход, который за кулисами отображает UpdatePersonDTO вместо Person.

Единственная "проблема" может заключаться в том, что это действительно идет вразрез с общим ожиданием.

Промежуточным решением может быть POST (или PUT) /person/{id}/mutables, которые могут принимать UpdatePersonDTO.

Edit: или parhaps более очевидно: PUT / person / {id} / name, который принимает аргумент PersonName, содержащий два поля.

Когда речь заходит о строгих правилах покоя (насколько такие правила вообще существуют:/), вы должны отправить всю сущность в PUT. Теперь вы можете:

  1. молча игнорировать поля, которые не могут быть обновлены-рекомендуется в некоторых случаях, но должны быть задокументированы.
  2. вызовите исключение, если вы обнаружите, что полю, которое не может быть обновлено, было присвоено новое значение.
  3. вместо использования PUT, используйте PATCH, который может обновить группу полей, и вся сущность не является необходимой, например, только первый и фамилия может быть отправлена.
Лично я считаю, что лучший вариант-это 1 или 3. Чего я не предлагаю, так это вводить новые конечные точки, как это предлагает @morsor. Такие конечные точки всегда вносят беспорядок. Как правило, чем меньше конечных точек используется, тем лучше (чище, проще для понимания) API.