Edit

Share via


Batch Support

Applies To:# OData WebApi v7 for aspnet webapi supported Green circle with a checkmark inside it. OData AspNet WebApi V7# OData Webapi for Webapi supported Green circular checkmark icon to indicate a success. OData AspNet WebApi V6

Batch requests allow grouping multiple operations into a single HTTP request payload and the service will return a single HTTP response with the response to all operations in the requests. This way, the client can optimize calls to the server and improve the scalability of its service.

Please refer to OData Protocol for more detail about batch, and Batch in ODL for batch in ODL client.

Enable Batch in Web API OData Service

It is very easy to enable batch in an OData service which is built by Web API OData.

Add Batch Handler

public static void Register(HttpConfiguration config) { var odataBatchHandler = new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer); config.MapODataServiceRoute("odata", "odata", GetModel(), odataBatchHandler); } 

As above, we only need to create a new batch handler and pass it when mapping routing for OData service. Batch will be enabled.

For testing, we can POST a request with batch body to the baseurl/$batch:

 POST https://localhost:14409/odata/$batch HTTP/1.1 User-Agent: Fiddler Host: localhost:14409 Content-Length: 1244 Content-Type: multipart/mixed;boundary=batch_d3bcb804-ee77-4921-9a45-761f98d32029 --batch_d3bcb804-ee77-4921-9a45-761f98d32029 Content-Type: application/http Content-Transfer-Encoding: binary GET https://localhost:14409/odata/Products(0) HTTP/1.1 OData-Version: 4.0 OData-MaxVersion: 4.0 Accept: application/json;odata.metadata=minimal Accept-Charset: UTF-8 User-Agent: Microsoft ADO.NET Data Services --batch_d3bcb804-ee77-4921-9a45-761f98d32029 Content-Type: multipart/mixed;boundary=changeset_77162fcd-b8da-41ac-a9f8-9357efbbd --changeset_77162fcd-b8da-41ac-a9f8-9357efbbd Content-Type: application/http Content-Transfer-Encoding: binary Content-ID: 1 DELETE https://localhost:14409/odata/Products(0) HTTP/1.1 OData-Version: 4.0 OData-MaxVersion: 4.0 Accept: application/json;odata.metadata=minimal Accept-Charset: UTF-8 User-Agent: Microsoft ADO.NET Data Services --changeset_77162fcd-b8da-41ac-a9f8-9357efbbd-- --batch_d3bcb804-ee77-4921-9a45-761f98d32029 Content-Type: application/http Content-Transfer-Encoding: binary GET https://localhost:14409/odata/Products HTTP/1.1 OData-Version: 4.0 OData-MaxVersion: 4.0 Accept: application/json;odata.metadata=minimal Accept-Charset: UTF-8 User-Agent: Microsoft ADO.NET Data Services --batch_d3bcb804-ee77-4921-9a45-761f98d32029-- 

And the response should be:

 HTTP/1.1 200 OK Cache-Control: no-cache Pragma: no-cache Content-Type: multipart/mixed; boundary=batchresponse_5667121d-ca2f-458d-9bae-172f04cdd411 Expires: -1 Server: Microsoft-IIS/8.0 OData-Version: 4.0 X-AspNet-Version: 4.0.30319 X-SourceFiles: =?UTF-8?B?YzpcdXNlcnNcbGlhbndcZG9jdW1lbnRzXHZpc3VhbCBzdHVkaW8gMjAxM1xQcm9qZWN0c1xUZXN0V2ViQVBJUmVsZWFzZVxUZXN0V2ViQVBJUmVsZWFzZVxvZGF0YVwkYmF0Y2g=?= X-Powered-By: ASP.NET Date: Wed, 06 May 2015 07:34:29 GMT Content-Length: 1449 --batchresponse_5667121d-ca2f-458d-9bae-172f04cdd411 Content-Type: application/http Content-Transfer-Encoding: binary HTTP/1.1 200 OK Content-Type: application/json; odata.metadata=minimal; charset=utf-8 OData-Version: 4.0 { "@odata.context":"https://localhost:14409/odata/$metadata#Products/$entity","ID":0,"Name":"0Name" } --batchresponse_5667121d-ca2f-458d-9bae-172f04cdd411 Content-Type: multipart/mixed; boundary=changesetresponse_e2f20275-a425-404a-8f01-c9818aa63610 --changesetresponse_e2f20275-a425-404a-8f01-c9818aa63610 Content-Type: application/http Content-Transfer-Encoding: binary Content-ID: 1 HTTP/1.1 204 No Content --changesetresponse_e2f20275-a425-404a-8f01-c9818aa63610-- --batchresponse_5667121d-ca2f-458d-9bae-172f04cdd411 Content-Type: application/http Content-Transfer-Encoding: binary HTTP/1.1 200 OK Content-Type: application/json; odata.metadata=minimal; charset=utf-8 OData-Version: 4.0 { "@odata.context":"https://localhost:14409/odata/$metadata#Products","value":[ { "ID":1,"Name":"1Name" },{ "ID":2,"Name":"2Name" },{ "ID":3,"Name":"3Name" },{ "ID":4,"Name":"4Name" },{ "ID":5,"Name":"5Name" },{ "ID":6,"Name":"6Name" },{ "ID":7,"Name":"7Name" },{ "ID":8,"Name":"8Name" },{ "ID":9,"Name":"9Name" } ] } --batchresponse_5667121d-ca2f-458d-9bae-172f04cdd411-- 

Setting Batch Quotas

DefaultODataBatchHandler contains some configuration, which can be set by customers, to customize the handler. For example, the following code will only allow a maximum of 8 requests per batch and 5 operations per ChangeSet.

var odataBatchHandler = new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer); odataBatchHandler.MessageQuotas.MaxPartsPerBatch = 8; odataBatchHandler.MessageQuotas.MaxOperationsPerChangeset = 5; 

Enable/Disable continue-on-error in Batch Request

We can handle the behavior upon encountering a request within the batch that returns an error by preference odata.continue-on-error, which is specified by OData V4 spec.

Enable Preference odata.continue-on-error

Preference odata.continue-on-error makes no sense by default, and service returns the error for that request and continue processing additional requests within the batch as default behavior.

To enable odata.continue-on-error, please refer to section 4.20 Prefer odata.continue-on-error for details.

Request Without Preference odata.continue-on-error

For testing, we can POST a batch request without Preference odata.continue-on-error:

	POST https://localhost:9001/DefaultBatch/$batch HTTP/1.1	Accept: multipart/mixed	Content-Type: multipart/mixed; boundary=batch_abbe2e6f-e45b-4458-9555-5fc70e3aebe0	Host: localhost:9001	Content-Length: 633	Expect: 100-continue	Connection: Keep-Alive	--batch_abbe2e6f-e45b-4458-9555-5fc70e3aebe0	Content-Type: application/http	Content-Transfer-Encoding: binary	GET https://localhost:9001/DefaultBatch/DefaultBatchCustomer(0) HTTP/1.1	--batch_abbe2e6f-e45b-4458-9555-5fc70e3aebe0	Content-Type: application/http	Content-Transfer-Encoding: binary	GET https://localhost:9001/DefaultBatch/DefaultBatchCustomerfoo HTTP/1.1	--batch_abbe2e6f-e45b-4458-9555-5fc70e3aebe0	Content-Type: application/http	Content-Transfer-Encoding: binary	GET https://localhost:9001/DefaultBatch/DefaultBatchCustomer(1) HTTP/1.1	--batch_abbe2e6f-e45b-4458-9555-5fc70e3aebe0-- The response should be:	HTTP/1.1 200 OK	Content-Length: 820	Content-Type: multipart/mixed; boundary=batchresponse_b49114d7-62f7-450a-8064-e27ef9562eda	Server: Microsoft-HTTPAPI/2.0	OData-Version: 4.0	Date: Wed, 12 Aug 2015 02:23:10 GMT	--batchresponse_b49114d7-62f7-450a-8064-e27ef9562eda	Content-Type: application/http	Content-Transfer-Encoding: binary	HTTP/1.1 200 OK	Content-Type: application/json; odata.metadata=minimal; odata.streaming=true	OData-Version: 4.0	{ "@odata.context":"https://localhost:9001/DefaultBatch/$metadata#DefaultBatchCustomer/$entity","Id":0,"Name":"Name 0"	}	--batchresponse_b49114d7-62f7-450a-8064-e27ef9562eda	Content-Type: application/http	Content-Transfer-Encoding: binary	HTTP/1.1 404 Not Found	Content-Type: application/json; charset=utf-8	{"Message":"No HTTP resource was found that matches the request URI 'https://localhost:9001/DefaultBatch/DefaultBatchCustomerfoo'.","MessageDetail":"No route data was found for this request."}	--batchresponse_b49114d7-62f7-450a-8064-e27ef9562eda-- 

Service returned error and stop processing.

Request With Preference odata.continue-on-error

Now POST a batch request with Preference odata.continue-on-error:

	POST https://localhost:9001/DefaultBatch/$batch HTTP/1.1	Accept: multipart/mixed	prefer: odata.continue-on-error	Content-Type: multipart/mixed; boundary=batch_abbe2e6f-e45b-4458-9555-5fc70e3aebe0	Host: localhost:9001	Content-Length: 633	Expect: 100-continue	Connection: Keep-Alive	--batch_abbe2e6f-e45b-4458-9555-5fc70e3aebe0	Content-Type: application/http	Content-Transfer-Encoding: binary	GET https://localhost:9001/DefaultBatch/DefaultBatchCustomer(0) HTTP/1.1	--batch_abbe2e6f-e45b-4458-9555-5fc70e3aebe0	Content-Type: application/http	Content-Transfer-Encoding: binary	GET https://localhost:9001/DefaultBatch/DefaultBatchCustomerfoo HTTP/1.1	--batch_abbe2e6f-e45b-4458-9555-5fc70e3aebe0	Content-Type: application/http	Content-Transfer-Encoding: binary	GET https://localhost:9001/DefaultBatch/DefaultBatchCustomer(1) HTTP/1.1	--batch_abbe2e6f-e45b-4458-9555-5fc70e3aebe0-- Service returns the error for that request and continue processing additional requests within the batch:	HTTP/1.1 200 OK	Content-Length: 1190	Content-Type: multipart/mixed; boundary=batchresponse_60fec4c2-3ce7-4900-a05a-93f180629a11	Server: Microsoft-HTTPAPI/2.0	OData-Version: 4.0	Date: Wed, 12 Aug 2015 02:27:45 GMT	--batchresponse_60fec4c2-3ce7-4900-a05a-93f180629a11	Content-Type: application/http	Content-Transfer-Encoding: binary	HTTP/1.1 200 OK	Content-Type: application/json; odata.metadata=minimal; odata.streaming=true	OData-Version: 4.0	{ "@odata.context":"https://localhost:9001/DefaultBatch/$metadata#DefaultBatchCustomer/$entity","Id":0,"Name":"Name 0"	}	--batchresponse_60fec4c2-3ce7-4900-a05a-93f180629a11	Content-Type: application/http	Content-Transfer-Encoding: binary	HTTP/1.1 404 Not Found	Content-Type: application/json; charset=utf-8	{"Message":"No HTTP resource was found that matches the request URI 'https://localhost:9001/DefaultBatch/DefaultBatchCustomerfoo'.","MessageDetail":"No route data was found for this request."}	--batchresponse_60fec4c2-3ce7-4900-a05a-93f180629a11	Content-Type: application/http	Content-Transfer-Encoding: binary	HTTP/1.1 200 OK	Content-Type: application/json; odata.metadata=minimal; odata.streaming=true	OData-Version: 4.0	{ "@odata.context":"https://localhost:9001/DefaultBatch/$metadata#DefaultBatchCustomer/$entity","Id":1,"Name":"Name 1"	}	--batchresponse_60fec4c2-3ce7-4900-a05a-93f180629a11--