如何在Web API中更新集合?

问题描述 投票:2回答:1

我有一个基本的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; }
}

我想介绍的用例:

  1. 添加很多OrderOrderItems
  2. 更新Order的属性,例如IsVoided
  3. 更新Order的项目(一次更新多个项目)。含义-用户将在UI中更改多个项目,并且在按下“保存”时将发送请求。这包括更新当前项目,还添加新项目或删除项目。不允许部分成功。

覆盖每个用例的API URI:

  1. 添加具有大量OrderOrderItems:具有有效负载的[POST] /api/orders/
{
    "customerId": 805,
    "isVoided": "false",
    "items": [
        {
            "itemId": 112233,
            "quantity": 25,
            "price": 50
        },
        {
            "itemId": 445566,
            "quantity": 20,
            "price": 40
        }
    ]
}
  1. 更新Order的属性,例如IsVoided(但不是项目):[PATCH] /api/orders/{orderId}
[
  {
      "op": "replace",
      "path": "/IsVoided",
      "value": true
  }
]
  1. 更新Order的项目(一次更新多个项目)

这是我遇到的问题...我有一些想法:

解决方案A:一次更新订单的项目,因此端点:

  • [[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:通过使用有效负载更新订单:[PUT] /api/orders/{orderId}来立即更新订单的项目:

{
    "customerId": 805,
    "isVoided": "false",
    "items": [
        {
            "itemId": 112233,
            "quantity": 25,
            "price": 50
        },
        {
            "itemId": 445566,
            "quantity": 20,
            "price": 40
        }
    ]
}

优点:性能,不允许部分成功。

缺点:如果用户更新了50件商品,删除了50件商品并将新的50件商品添加到订单,那么在一个请求(对PUT实体的Order请求)中,我们将本质上在不同的商品上添加,更新和删除50件商品实体-OrderItem。我担心这是否是良好的RESTful做法。

解决方案C:通过更新...集合:带有有效负载的[PUT] /api/orders/{orderId}/items来立即更新订单的项目:

[
    {
        "itemId": 112233,
        "quantity": 25,
        "price": 50
    },
    {
        "itemId": 445566,
        "quantity": 20,
        "price": 40
    }
]

有效负载中的集合将完全替换系统中的集合,包括添加和删除操作。

优点:性能,不允许部分成功,您不会与父实体混淆。

缺点:这是在集合上调用PUT请求的良好做法。通常,当您拥有PUT时,URI会以某种ID结束(您正在更新实体)。在这种情况下,URI将以“项目”结尾。这是怎么做的?

解决方案D:可能使用PATCH的其他解决方案?以前从未做过,但是也许可以为PATCH实体发送Order,从而修补Items的集合。以JsonDocument的价值,我将传递新项目的集合,要删除的项目和更新的项目?

因此,我的问题是:这些解决方案中哪种最适合这种情况? A,B,C或(如果存在)D?还是其他我没想到的解决方案?

c# rest asp.net-web-api url-routing asp.net-core-webapi
1个回答
1
投票

如果您没有很多项目,解决方案A完全可以。它不适合您的情况,因为如果您有很多请求,它会使您的api变得不友好。

解决方案B一次发送了很多。它坚持使用完整资源对象进行更新的做法,甚至还有一个http状态代码来指示部分成功。响应对象是一个让消费者知道成功的新URL并指出失败的URL的考虑因素(如果有)以及原因。随它或D。

解决方案C并没有那么轻松。您实际上并没有更新任何单一资源,因此对于消费者而言将很难理解。

解决方案D是B和C的合并。我希望在这里使用它,因为您并没有真正更新完整的对象。您可以使用与B相同的网址

几个扩展超文本传输​​协议(HTTP)的应用程序需要功能来进行部分资源修改。现有的HTTP PUT方法仅允许完全替换文档。该提案添加了新的HTTP方法PATCH,以修改现有的HTTP资源。– RFC 5789

© www.soinside.com 2019 - 2024. All rights reserved.