【发布时间】:2019-12-14 01:23:18
【问题描述】:
我有一个基本的Order-OrderItem 情况,我正在努力如何在一个请求中更新项目(或者我是否应该?)让我解释一下,最后我会问这个问题。
型号:
public class Order
{
public int OrderId { get; set; }
public string CustomerId { get; set; }
public bool IsVoided { get; set; }
public List<OrderItem> Items { get; set; }
}
public class OrderItem
{
public int OrderItemId { get; set; }
public string Name { get; set; }
public int Quantity { get; set; }
public int Price { get; set; }
}
我想介绍的用例:
- 添加
Order和大量OrderItems - 更新
Order的属性,例如IsVoided - 更新
Order的项目(一次多个项目)。含义 - 用户将更改 UI 中的多个项目,并在按下“保存”时发送请求。这包括更新当前项目,还包括添加新项目或删除项目。不应允许部分成功。
涵盖每个用例的 API URI:
- 添加
Order和大量OrderItems:[POST] /api/orders/和有效负载:
{ "customerId": 805, "isVoided": "false", "items": [ { "itemId": 112233, "quantity": 25, "price": 50 }, { "itemId": 445566, "quantity": 20, "price": 40 } ] }
- 更新
Order的属性,例如IsVoided(但不是项目):[PATCH] /api/orders/{orderId}
[ { "op": "replace", "path": "/IsVoided", "value": true } ]
- 更新
Order的项目(一次多个项目)
这是我遇到的问题...我有一些想法:
方案A:一一更新Order的商品,所以端点:
-
[POST] /api/orders/{orderId}/items,有效载荷:{ "quantity": 25, "price": 50 } -
[PUT] /api/orders/{orderId}/items/{itemId},有效载荷:{ "quantity": 25, "price": 50 } [DELETE] /api/orders/{orderId}/items/{itemId}
优点:干净的架构。您使用实体的端点添加/更新/删除实际的实体。
缺点:如果用户更新 500 个项目并单击“保存”,将导致向服务器发出 500 个请求。此外,它将接受部分成功
解决方案 B: 通过使用有效负载更新 Order:[PUT] /api/orders/{orderId} 来立即更新 Order 的项目:
{ "customerId": 805, "isVoided": "false", "items": [ { "itemId": 112233, "quantity": 25, "price": 50 }, { "itemId": 445566, "quantity": 20, "price": 40 } ] }
优点:性能,不允许部分成功。
缺点:如果用户更新 50 件商品,删除 50 件并在订单中添加新的 50 件商品,在一个请求(Order 实体上的 PUT 请求)中,我们基本上将添加、更新、删除 50 件商品不同的实体 - OrderItem。我担心这是否是好的RESTful 做法。
解决方案 C: 通过更新...集合:[PUT] /api/orders/{orderId}/items 和有效负载:
[ { "itemId": 112233, "quantity": 25, "price": 50 }, { "itemId": 445566, "quantity": 20, "price": 40 } ]
payload中的集合,将完全替代系统中的集合,包括添加和删除操作。
优点:性能,不允许部分成功,不要与父实体混淆。
缺点:在集合上调用 PUT 请求是一个好习惯吗?通常当您拥有PUT 时,URI 以某种 ID 结尾(您正在更新实体)。在这种情况下,URI 将以“items”结尾。是这样的吗?
解决方案 D: 一个不同的解决方案,可能是PATCH?以前从未这样做过,但也许可以为Order 实体发送PATCH,修补项目集合。在 JsonDocument 的值中,我会传递新项目的集合、要删除的项目和更新的项目吗?
所以,我的问题是:哪种解决方案最适合这种情况? A、B、C 还是(如果存在)D?还是我没有想到的其他解决方案?
【问题讨论】:
-
似乎解决方案 B 最符合您的要求,但它让您担心,因为在一个请求中会发生很多事情。如果每个部分(添加/删除项目等)在概念上都是一件事 - 订单更新,我真的不认为这是一个问题。
-
解决方案 B 对我来说似乎是最好的解决方案。
-
解决方案 B 对我来说似乎是最好的解决方案。如果你愿意,你也可以添加 A,但在内部我可能会调用 B。你想在事务中一次更新,所以发送 50 个单个请求对我来说听起来是错误的。
标签: c# rest asp.net-web-api url-routing asp.net-core-webapi