如何在Web API中更新集合? [英] How to update a collection in Web API?

查看:86
本文介绍了如何在Web API中更新集合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基本的Order-OrderItem情况,我在为如何在一个请求中更新项目而苦苦挣扎(或者我应该吗?)让我解释一下,我将在最后问这个问题./p>

型号:

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. 添加具有很多OrderItems
  2. Order
  3. 更新Order的属性,例如IsVoided
  4. 更新Order的项目(一次更新多个项目).含义-用户将在UI中更改多个项目,并且在按下保存"时将发送请求.这包括更新当前项目,还包括添加新项目或删除项目.不允许部分成功.

涵盖每个用例的API URI:

  1. 添加具有大量OrderItemsOrder:[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件商品,那么在一个请求(对Order实体的PUT请求)中,我们将实质上添加,更新,删除订单上的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的其他解决方案?以前从未做过,但是也许可以为Order实体发送PATCH,以修补Items的集合.以JsonDocument的价值,我将传递新项目的集合,要删除的项目和更新的项目?

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

解决方案

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

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

解决方案C并非那么令人安心.您实际上并没有更新任何单一资源,对于消费者而言,这将是很难理解的.

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

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

I have a basic Order-OrderItem situation and I'm struggling how to update Items in one request (or if should I?) Let me explain and I'm gonna ask the question at the end.

Models:

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; }
}

Use cases I want to cover:

  1. Add Order with lots of OrderItems
  2. Update Order's properties, like IsVoided
  3. Update Order's items (multiple items at once). Meaning - user will change multiple items in the UI and the request will be sent when pressed "Save". That includes, updating the current items, but also adding new items or removing items as well. Partial success shouldn't be allowed.

API's URIs to cover each use case:

  1. Add Order with lots of OrderItems: [POST] /api/orders/ with payload:

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

  1. Update Order's properties, like IsVoided (but NOT items): [PATCH] /api/orders/{orderId}

[
  {
      "op": "replace",
      "path": "/IsVoided",
      "value": true
  }
]

  1. Update Order's items (multiple items at once)

Here's the problem I'm having... I have a few ideas:

Solution A: Update Order's items one by one, so endpoints:

  • [POST] /api/orders/{orderId}/items, with payload: { "quantity": 25, "price": 50 }
  • [PUT] /api/orders/{orderId}/items/{itemId}, with payload: { "quantity": 25, "price": 50 }
  • [DELETE] /api/orders/{orderId}/items/{itemId}

Pros: Clean architecture. You Add/Update/Delete the actually Entity, using Entity's endpoint.

Cons: If user updates 500 items and click "Save", it will result in 500 requests to the server. Also, it will accept partial success

Solution B: Update Order's items at once by updating the Order: [PUT] /api/orders/{orderId} with payload:

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

Pros: Performance, Partial success will not be allowed.

Cons: If user updates 50 items, deletes 50 and adds new 50 items to the order, in one request (a PUT request on the Order entitiy) we will esentially add, update, remove 50 items on a different entity - OrderItem. I'm concerned if this is the good RESTful practice.

Solution C: Update Order's items at once by updating... the collection: [PUT] /api/orders/{orderId}/items with payload:

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

The collection in the payload, will completely replace the collection in the system, including Add and Remove operations.

Pros: Performance, Partial success will not be allowed, You don't mess with the parent Entity.

Cons: Is this a good practice to call PUT request on a collection. Ususally when you have PUT, the URI ends with some kinda ID (you're updating an entitiy). In this case, the URI will end with "items". Is this how it's done?

Solution D: A different solution, possibly with PATCH? Never done that before, but maybe it's possible to send PATCH for an Order entity, patching the collection of Items. In JsonDocument's value, I would pass the collection of new items, items to remove and updated items?

So, my question is: Which of these solution is the best for this situation? A, B, C or (if exists)D? Or other solution I didn't think about?

解决方案

Solution A is totally fine if you don't have many items. It does not suit your case as it makes your api chatty if you have many requests.

Solution B sends a lot at once. It adheres to the practice of updating with the full resource object and there is even an http status code to indicate partial success. Response object is a consideration to let the consumer know the new urls of successful and indicate the ones that failed if any and why. Go with it or D.

Solution C is not that restful. You are not really updating any single resource and it will be hard to understand for the consumers.

Solution D is a merge of B and C. I would expect it to be used here as you are not really updating the full object. You can use the same url as B

Several applications extending the Hypertext Transfer Protocol (HTTP) require a feature to do partial resource modification. The existing HTTP PUT method only allows a complete replacement of a document. This proposal adds a new HTTP method, PATCH, to modify an existing HTTP resource. – RFC 5789

这篇关于如何在Web API中更新集合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆