简体   繁体   English

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

[英]How to Design a Restful API for Bulk Inserts and Updates?

I have a Web API application and I'm using the below url for both bulk (tens or hundreds) inserts and updates which return just OK or Failed. 我有一个Web API应用程序,我使用下面的url进行批量(数十或数百)插入和更新,只返回OK或Failed。

POST api/v1/products

which is mapped to my action: 它映射到我的动作:

public HttpResponseMessage PostProducts(PostProductsRequest request)
{

...
}

PostProductsRequest object contains a Products property of type List. PostProductsRequest对象包含List类型的Products属性。

If the Id property exists for a Property, I update it otherwise it'd indicate an insert. 如果属性的Id属性存在,我会更新它,否则它会指示插入。

But I'm just wondering whether I should use Post for Bulk Inserts only and Put for Bulk Updates, not sure. 但我只是想知道我是否应该只使用Post for Bulk Inserts和Put for Bulk Updates,不确定。 What's the best practice and advantage of each approach? 每种方法的最佳实践和优势是什么?

How to Design a Restful API for Bulk Inserts and Updates? 如何为批量插入和更新设计一个Restful API?

Either method can be used, depending on your requisites, but this doesn't mean they don't have significant differences. 根据您的要求,可以使用任何一种方法,但这并不意味着它们没有显着差异。 HTTP methods are not CRUD. HTTP方法不是CRUD。 PUT or POST are not Create and Update, or the other way around. PUT或POST不是创建和更新,反之亦然。

PUT completely replaces the resource at the given URI with the entity provided, so it can be used to create and also to update, but only if it contains the full representation. PUT 完全用提供的实体替换给定URI的资源,因此它可以用于创建和更新,但前提是它包含完整的表示。 A GET request made immediately after a PUT should return the same resource. 在PUT之后立即发出的GET请求应该返回相同的资源。 The representation may be exactly the same, although it's possible for the service to add default values that were missing from the PUT'ed representation. 表示可能完全相同,但服务可能会添加PUT表示中缺少的默认值。

POST tells the server that the entity being provided is subordinated to the resource at the given URI, and they have an agreement on what it should be done with that. POST告诉服务器所提供的实体从属于给定URI的资源,并且他们就应该如何处理它达成一致。 It might be anything, a create, an update, any operation that isn't standardized by HTTP itself. 它可能是任何东西,创建,更新,任何未被HTTP本身标准化的操作。

With this in mind, a bulk insert or update with PUT is only RESTful if you're replacing the whole collection identified by the URI. 考虑到这一点,如果您要替换URI标识的整个集合,则使用PUT进行批量插入或更新只是RESTful。 This doesn't have to be necessarily your whole collection associated with that media type. 这不一定是与该媒体类型相关的整个集合。 The URI can have a querystring slicing the dataset, and you perform the bulk operation on that slice only. URI可以具有对数据集进行切片的查询字符串,并且仅对该切片执行批量操作。

For instance, if you have the following collection resource: 例如,如果您有以下集合资源:

GET /api/products

Represented by: 代表人:

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

And you want to add three more products, a bulk operation with PUT would have to append your new products to the existent and send the whole collection back: 并且您想要添加另外三个产品,PUT的批量操作必须将您的新产品附加到现有产品并将整个集合发回:

PUT /api/products

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

However, if you have a filter constraint you can apply to /api/products that would return an empty collection on the GET above, then it would be fine to do the PUT only with the new products to that filtered resource. 但是,如果您有一个过滤器约束,您可以应用于将在上面的GET上返回空集合的/api/products ,那么只有将新产品用于该过滤资源才能进行PUT。 For instance, let's say the products above can be filtered by a partner attribute, they have partner x and you're adding for partner y: 例如,假设上面的产品可以通过合作伙伴属性进行过滤,他们有合作伙伴x,而您正在为合作伙伴y添加:

In that case, it's fine for you to do: 在这种情况下,你可以这样做:

PUT /api/products?partner=y

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

And a GET /api/products after that returns: 然后返回GET /api/products

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

As long as GET /api/products?partner=x returns: 只要GET /api/products?partner=x返回:

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

And GET /api/products?partner=y returns: GET /api/products?partner=y return:

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

This might seem complicated and sometimes it looks like it's better to use POST instead of PUT, but keep in mind that the whole operation above is standardized. 这可能看起来很复杂,有时看起来最好使用POST而不是PUT,但请记住,上面的整个操作都是标准化的。 It's using PUT exactly as it's intended to be used. 它正在使用PUT,就像它打算使用的那样。 The operations can be more straightforward with POST, but they are not standardized and you'll have to design and document your own syntax for it. 使用POST时,操作可以更简单,但它们不是标准化的,您必须为它设计和记录自己的语法。

I would recommend to use POST to create and PUT to update (actually create or update as it is indempotent ). 我建议使用POST来创建和PUT进行更新(实际创建或更新,因为它是无效的 )。

From the RESTful Webservices Cookbook (O'Reilly): 来自RESTful Webservices Cookbook (O'Reilly):

Use POST and a collection resource to create a number of similar resources at once. 使用POST和集合资源一次创建许多类似的资源。 Let clients include information about the resources to be created in the request. 让客户端包含有关要在请求中创建的资源的信息。 Assign a URI for all the resources created, and redirect the client to the collection using response code 303 (See Other). 为所有创建的资源分配URI,并使用响应代码303将客户端重定向到集合(请参阅其他)。 A representation of this resource includes links to all the newly created resources. 此资源的表示包括指向所有新创建的资源的链接。

To update or delete a number of similar resources in bulk, use a single URI that can return a representation containing information about all those resources. 要批量更新或删除大量类似资源,请使用单个URI,该URI可返回包含有关所有这些资源的信息的表示。 Submit a PUT request to that URI with information about the resources to be updated or a DELETE request to delete those resources. 向该URI提交PUT请求,其中包含有关要更新的资源的信息或删除这些资源的DELETE请求。 In all these cases, ensure that the processing of the request is atomic. 在所有这些情况下,请确保请求的处理是原子的。

The most "standards compliant" way for batch operations in RESTful Web services is to use one of the various 'collection' approaches (ie DELETE /mail?&id=0&id=1&id=2 ) or you could use a batching handler to simply the process. RESTful Web服务中批处理操作最“符合标准”的方法是使用各种“集合”方法之一(即DELETE /mail?&id=0&id=1&id=2 ),或者您可以使用批处理程序来简化该过程。

Honestly, I use the exact same pattern as you do except for the fact that I use POST for object creation and PUT for updates only (which is the standard way of doing it). 老实说,我使用与你完全相同的模式,除了我使用POST进行对象创建和PUT只进行更新(这是执行此操作的标准方法)。 Also POST should return 201 - Created along with the created object and PUT should return 204 - No Content with no data, if the operation succeeds. POST应返回201 -与创建的对象一起创建,如果操作成功, PUT应返回204 -没有数据的内容 Of course, as you're doing bulk creation, you may opt not to return the array of newly created objects with POST . 当然,在进行批量创建时,您可以选择不使用POST返回新创建的对象数组。

To summarize it: 总结一下:

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

Update : vNext of ASP.NET Web API will have batching built in ! 更新 :ASP.NET Web API的vNext将内置批处理

I just happened to be looking at the HTTP 1.1 method definition and was reminded of this question. 我刚刚看到HTTP 1.1方法定义 ,并提醒了这个问题。

The PUT method requests that the enclosed entity be stored under the supplied Request-URI. PUT方法请求将所包含的实体存储在提供的Request-URI下。 If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. 如果Request-URI引用已经存在的资源,则封闭的实体应该被视为驻留在源服务器上的实体的修改版本。 If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI. 如果Request-URI未指向现有资源,并且该URI能够被请求用户代理定义为新资源,则源服务器可以使用该URI创建资源。

This would indicate to me that if you were to use PUT and the payload contained a not existing resource with enough information to create it then it should be created and therefore PUT would be the correct method verb in a bulk operation that can create & update resources. 这将向我表明,如果你使用PUT并且有效负载包含一个不存在的资源,并且有足够的信息来创建它,那么它应该被创建,因此PUT将是批量操作中可以创建和更新资源的正确方法动词。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM