RESTful端点的输入DTO应该与输出DTO匹配吗?

RESTful端点的输入DTO应该与输出DTO匹配吗?,rest,restful-architecture,Rest,Restful Architecture,我正在开发一个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 DateO

我正在开发一个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
不能更改,接受它作为输入是否被认为是RESTful的:

public class UpdatePersonDto
{
    public string Surname { get; set; }
    public string GivenName { get; set; }
}
这意味着当使用
GET
时,我会让这个端点
api/person/{id}
返回
person
,当使用
PUT
时,接受作为输入
UpdatePersonDto
。这听起来不对,但我不确定我是否只是在妄想


因此,我想我的问题可以归结为:是否适合接受给定资源端点上与该端点将返回的数据结构不同的数据结构?

其他共识似乎是,在使用PUT更新时,可以提供整个实体进行替换

从编程的角度来说,让PUT/person/{id}接受在后台映射到UpdatePersonDTO而不是person的输入是可行的

唯一的“问题”可能是它确实违背了人们的普遍期望

中间解决方案可以是POST(或PUT)/person/{id}/mutables,它可以接受UpdatePersonDTO


Edit:或parhaps更明显:PUT/person/{id}/name,它接受一个包含两个字段的PersonName参数。

当涉及REST严格规则时(只要这些规则存在:/),您应该将整个实体发送到
PUT
。现在您可以:

  • 默默地忽略无法更新的字段-在某些情况下建议,但应记录
  • 如果检测到无法更新的字段被赋予新值,则引发异常
  • 不要使用
    PUT
    ,而是使用
    PATCH
    ,它可以更新一组字段,并且不需要整个实体,例如,只能发送名字和姓氏

  • 我个人认为最好的选择是1或3。我不建议像@morsor建议的那样引入新的端点。这样的端点总是会带来混乱。通常,使用的端点越少,API就越好(越干净,越容易理解)。

    这对于PUT非常有意义,在PUT中,您可以获取资源的副本,对其进行修改,然后将其发送回。但是对于POST呢?在创建过程中,一些属性可能会在服务器端进行计算。我不确定您认为问题出在哪里。PUT应该是幂等的(对于客户端),而使用POST清楚地说明应该在服务器上执行非幂等操作。在这种情况下,我不是说请求是否在服务器上以幂等方式处理,我说的是,发布一个DTO时只包含创建资源所需的字段,这是否被认为是正确的做法,还是应该发布一个实际的资源实例,并尽可能多地填充字段?因为REST不是一个标准,所以有很多灰色区域,留下了很多回旋余地。如果您能够在客户端填充整个对象,那么对整个对象执行标准PUT将100%符合REST最佳实践。你的其他解决方案是完全合法的,唯一的问题是你需要更好地记录它们,因为你没有遵循预期的最佳实践。下层选民-愿意评论吗?不幸的是,很少。向上投票。