22

我有一个 Web API 应用程序,我使用下面的 url 进行批量(数十或数百)插入和更新,它们返回正常或失败。

POST api/v1/products

映射到我的操作:

public HttpResponseMessage PostProducts(PostProductsRequest request)
{

...
}

PostProductsRequest 对象包含 List 类型的 Products 属性。

如果某个属性的 Id 属性存在,我会更新它,否则它会指示插入。

但我只是想知道我是否应该只将 Post 用于批量插入,而将 Put 用于批量更新,不确定。每种方法的最佳实践和优势是什么?

如何为批量插入和更新设计一个 Restful API?

4

4 回答 4

9

根据您的要求,可以使用任何一种方法,但这并不意味着它们没有显着差异。HTTP 方法不是 CRUD。PUT 或 POST 不是创建和更新,反之亦然。

PUT用提供的实体完全替换给定 URI 处的资源,因此它可以用于创建和更新,但前提是它包含完整表示。在 PUT 之后立即发出的 GET 请求应该返回相同的资源。表示可能完全相同,尽管服务可以添加 PUT 表示中缺少的默认值。

POST 告诉服务器,提供的实体从属于给定 URI 的资源,并且他们就应该如何处理达成一致。它可能是任何东西,一个创建,一个更新,任何 HTTP 本身没有标准化的操作。

考虑到这一点,如果您要替换由 URI 标识的整个集合,则使用 PUT 进行批量插入或更新仅是 RESTful。这不一定是与该媒体类型关联的整个集合。URI 可以具有对数据集进行切片的查询字符串,并且您仅对该切片执行批量操作。

例如,如果您有以下集合资源:

GET /api/products

代表:

{'products': [product1, product2, product3]}

如果您想再添加三个产品,使用 PUT 的批量操作必须将您的新产品附加到现有产品并将整个集合发回:

PUT /api/products

{'products': [product1, product2, product3, product4, product5, product6]}

但是,如果您有一个过滤器约束,您可以应用/api/products该约束将在上面的 GET 上返回一个空集合,那么只对该过滤资源的新产品执行 PUT 就可以了。例如,假设上面的产品可以通过合作伙伴属性过滤,它们有合作伙伴 x,而您正在为合作伙伴 y 添加:

在这种情况下,您可以这样做:

PUT /api/products?partner=y

{'products': [product4, product5, product6]}

GET /api/products之后返回:

{'products': [product1, product2, product3, product4, product5, product6]}

只要GET /api/products?partner=x回报:

{'products': [product1, product2, product3]}

GET /api/products?partner=y返回:

{'products': [product4, product5, product6]}

这可能看起来很复杂,有时看起来最好使用 POST 而不是 PUT,但请记住,上面的整个操作都是标准化的。它完全按照预期使用 PUT。使用 POST 操作可以更直接,但它们不是标准化的,您必须为其设计和记录自己的语法。

于 2013-11-05T10:47:34.413 回答
6

我建议使用POSTto 创建和PUT更新(实际上是创建或更新,因为它是indempotent)。

来自RESTful Webservices Cookbook (O'Reilly):

使用 POST 和集合资源一次创建多个类似资源。让客户端在请求中包含有关要创建的资源的信息。为创建的所有资源分配一个 URI,并使用响应代码 303 将客户端重定向到集合(请参阅其他)。此资源的表示包括指向所有新创建资源的链接。

要批量更新或删除大量类似资源,请使用单个 URI,该 URI 可以返回包含有关所有这些资源的信息的表示。向该 URI 提交 PUT 请求,其中包含有关要更新的资源的信息或删除这些资源的 DELETE 请求。在所有这些情况下,请确保请求的处理是原子的。

于 2013-06-25T15:14:00.943 回答
3

我刚好在看HTTP 1.1 的方法定义,被提醒了这个问题。

PUT 方法请求将封闭的实体存储在提供的 Request-URI 下。如果 Request-URI 引用了一个已经存在的资源,封闭的实体应该被认为是在源服务器上的一个修改版本。如果 Request-URI 不指向现有资源,并且该 URI 能够被请求用户代理定义为新资源,则源服务器可以使用该 URI 创建资源。

这将向我表明,如果您要使用 PUT 并且有效负载包含一个不存在的资源,该资源具有足够的信息来创建它,那么应该创建它,因此 PUT 将是可以创建和更新资源的批量操作中的正确方法动词.

于 2013-06-26T13:45:07.783 回答
2

对于 RESTful Web 服务中的批处理操作,最“符合标准”的方式是使用各种“收集”方法之一(即DELETE /mail?&id=0&id=1&id=2),或者您可以使用批处理处理程序来简化处理。

老实说,我使用与您完全相同的模式,除了我仅POST用于对象创建和PUT更新(这是执行此操作的标准方式)。如果操作成功,还POST应该返回201 -与创建的对象一起创建,并且PUT应该返回204 - 没有数据的无内容。当然,当您进行批量创建时,您可以选择不使用POST.

总结一下:

POST api/products
  |
  |---> Success: 201 [NewObject1, NewObject2, ...]
  |---> Failure: Relevant error code as to why the operation failed

PUT api/products
  |
  |---> Success: 204
  |---> Failure: Relevant error code as to why the operation failed

更新: ASP.NET Web API 的 vNext 将内置批处理

于 2013-06-25T12:24:25.413 回答