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

时间:2013-06-25 08:32:44

标签: c# asp.net rest asp.net-web-api

我有一个Web API应用程序,我使用下面的url进行批量(数十或数百)插入和更新,只返回OK或Failed。

POST api/v1/products

映射到我的操作:

public HttpResponseMessage PostProducts(PostProductsRequest request)
{

...
}

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

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

但我只是想知道我是否应该只使用Post for Bulk Inserts和Put for Bulk Updates,不确定。每种方法的最佳实践和优势是什么?

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

4 个答案:

答案 0 :(得分: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时,操作可以更直接,但它们不是标准化的,您必须为它设计和记录自己的语法。

答案 1 :(得分:6)

我建议使用POST创建并PUT进行更新(实际创建或更新indempotent)。

来自RESTful Webservices Cookbook(O'Reilly):

  

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

     

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

答案 2 :(得分:2)

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

老实说,我使用与您完全相同的模式,除了我使用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将有batching built in

答案 3 :(得分:2)

我正好看着HTTP 1.1 method definition,并提醒了这个问题。

  

PUT方法请求将所包含的实体存储在提供的Request-URI下。如果Request-URI引用已经存在的资源,则封闭的实体应该被视为驻留在源服务器上的实体的修改版本。 如果Request-URI未指向现有资源,并且该URI能够被请求用户代理定义为新资源,则源服务器可以使用该URI创建资源。 < / p>

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