【问题标题】:How to design Multiple Patch requests in WebApi Core如何在 WebApi Core 中设计多个 Patch 请求
【发布时间】:2019-09-16 12:02:37
【问题描述】:

我想知道在 WebApi .Net Core 中设计多个资源更新的最佳方式是什么。

例如,我想为users资源启用以下功能

  • 更新用户密码
  • 更新用户角色
  • 更新用户详细信息(例如名字、姓氏等)

所以,根据REST教程和文章,我了解到我需要使用PATCH方法来更新部分资源。

我们在团队中进行了一些讨论,但我们对这两个选项感到困惑:

选项 1

为不同的操作实现多个 PATCH 路由

  • 补丁/api/users/{id}/password
  • 补丁/api/users/{id}/role
  • 补丁/api/users/{id}/details

选项 2

仅对整个资源实施单个 PATCH 操作。用户将发送 application/json-patch+json 进行部分更新。

  • PATCH /api/users/id(接受JsonPatchDocument参数)

我试图找到 Restful Route Namings 的最佳实践,其中大多数仅涵盖简单的 CRUD 活动或嵌套资源。

对于这种多重 UPDATE 操作,我可以知道命名路由的最佳做法是什么?还是深入研究它的术语?谢谢。

【问题讨论】:

  • 请注意,每个PATCH 请求都有一个路由/方法可以实现更好的授权控制。您可以使用此方法使用 AuthorizeAttribute 注释每个方法,以确保只有您想要更新的字段实际上由授权用户相应地更新(例如,仅允许管理员更新用户角色,或一般情况下:只允许 更新 )
  • 我认为最好的方法是将 PUT 与选项 2 一起使用。对我而言,PATCH 方法应该与 OData 或类似方法一起使用。
  • 当然,选项 2。另请参阅如何实现here

标签: rest asp.net-core-webapi patch


【解决方案1】:

PATCH 请求用于更新单个资源的一部分,即只应替换资源字段的特定子集。语义最好描述为“请根据我的更改请求更改 URL 标识的资源”。

  • PATCH 请求通常应用于单个资源,因为修补整个集合具有挑战性
  • PATCH 请求通常对不存在资源实例并不可靠
  • 在成功的PATCH 请求时,服务器将更新由有效负载中更改请求定义的 URL 寻址的部分资源
  • 成功的PATCH 请求通常会生成200204(如果资源已更新,有或没有返回更新的内容)

注意:由于正确实现PATCH 有点棘手,我强烈建议每个端点选择以下模式中的一个且仅一个。按优先顺序:

  1. 在可行的情况下,将PUT 与完整对象一起使用以更新资源(即根本不使用PATCH)。
  2. 尽可能将PATCH 与部分对象一起使用以仅更新资源的一部分。 (这基本上是JSON Merge Patch,一种专门的媒体类型application/merge-patch+json,它是部分资源表示。)
  3. PATCHJSON Patch 结合使用,这是一种专门的媒体类型application/json-patch+json,其中包含有关如何更改资源的说明。
  4. 如果请求未以媒体类型语义定义的方式修改资源,请使用 POST(对正在发生的事情进行正确描述)而不是 PATCH

选项 1 似乎是糟糕的设计,因为每个属性都会有很多端点。

选项 2 遵循 REST 建议并在 RFC 6902 中指定

您可以通过以下方式实现它:

  • Delta(Microsoft ASP.NET WebAPI OData 的一部分):它在使用 JSON 时存在一些数字问题。您还需要安装包含所有重要依赖项的软件包;
  • JSON Patch:客户端每次操作都要组织数据,请求的大小没有优化。
  • 使用Simple.HttpPatch 可以轻松应用部分更新
  • 另一个SimplePatch 实现

路线命名

  • 资源名称使用复数名词。不要混淆单数和复数名词。保持简单,所有资源只使用复数名词(users,而不是user

  • 如果每个资源有两个基本 URL,则第一个 URL 用于集合(列表);第二个是针对集合中的特定元素(/users/users/1

  • 如果您有关系,请为其使用子资源

/users/1/phones - 返回用户 1 的电话列表
/users/1/phones/1 - 返回用户 1 的电话号码 1

  • 在您的基本 URL 中保留动词。使用带有两个基本 URL 的 HTTP 请求方法 GETPOSTPUT/PATCHDELETE 进行 CRUD 操作。关键是开发人员可能不需要文档来了解 API 的行为方式。否则,您将拥有一长串 URL,并且没有一致的模式,这使得开发人员难以学习如何使用您的 API

  • 复杂的东西需要隐藏在? 后面。几乎每个 API 都有很多参数,您可以通过任何其他方式读取、更新、过滤和使用它们。但是所有这些参数都不应该在基地址中可见。最好在对基地址的引用中指定参数。

GET /users/1234?firstName=Bill&PhoneNumber="1111"

另见链接

【讨论】:

【解决方案2】:

将 PUT 与整个对象的 json 一起使用,只更改必要的内容

类似(使用 try-catch ofc)

[HttpPut("UpdateUser/{id}")]
public bool UpdateUser(string/int id, [FromBody]UrObject value)
{
    var item = UrObjRepo.WHere(w=> w.Key == id).FirstOrDefault();
    if (item==null)
    {
        return false; //not found item to update
    }
    UrObject.someValue = value.newValue.hasValue ? value : UrObject.someValue;
    ...
    UrObjRepo.update(UrObject);
}

在那个 JSON 中,你不能拥有所有属性......只有那些你想改变的人...... 原因:

UrObject.someValue = value.newValue.hasValue ? value : UrObject.someValue;

【讨论】:

    猜你喜欢
    • 2018-01-10
    • 2016-04-26
    • 1970-01-01
    • 1970-01-01
    • 2011-10-14
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多