【ASP.NET Web API教程】5.4 ASP.NET Web API批處理器

來源:互聯網
上載者:User

註:本文是【ASP.NET Web API系列教程】的一部分,如果您是第一次看本系列教程,請先看前面的內容。

Batching Handler for ASP.NET Web API
5.4 ASP.NET Web API批處理器

本文引自:http://bradwilson.typepad.com/blog/2012/06/batching-handler-for-web-api.html

Brad Wilson | June 20, 2012
作者:Brad Wilson | 日期:2012-6-20

While there is no batching standard built into the HTTP protocol, there is a standard for MIME encoding HTTP request and response messages ("application/http" with "msgtype=request" and "msgtype=response", respectively). ASP.NET Web API has built-in support for both MIME multipart as well as encoded request and response messages, so we have all the building blocks we need to make a simple batch request handler.
當批處理標準尚未進入HTTP協議時,就已經有了對HTTP請求和響應訊息進行編碼的MIME標準(分別採用“msgtype=request”和“msgtype=response”的“application/http”)。ASP.NET Web API對MIME的multipart(多部分內容類型)、以及經過編碼請求和響應訊息都有內建的支援,因此,我們擁有了製作簡單的請求批處理器的全部構建塊。

All we need to make this work is an endpoint which can accept a multipart batch (an invention of our own), which then parses the requests, runs them sequentially, and returns the responses back in a multipart batch response.
我們所要做的全部工作只是一個端點(endpoint),它可以接收一個multipart batch(多部批,一個我們自己發明的內容類型),然後用它對請求進行解析,按順序執行請求,並以一個multipart batch響應的形式返回一個響應。

Starting with a Web API project (built against the latest nightly build), I updated the Web API config to look like this:
從一個Web API項目(根據最新版建立的項目)開始,我修改了Web API的config,它看上去像這樣:

var batchHandler = new BatchHandler(config);
config.Routes.MapHttpRoute("batch", "api/batch", null, null, batchHandler);
config.Routes.MapHttpRoute("default", "api/{controller}/{id}", new { id = RouteParameter.Optional });

I've inserted the handler for "api/batch" as our endpoint for batching requests, using the new "route-specific endpoint handler" feature in Web API. Note that since its URL is "api/batch", I made sure to add it before the default API route.
我已經為“api/batch”插入了處理器,以此作為對請求進行批處理的端點,這種做法利用了Web API中的“路由專用的端點處理器”特性。注,由於它的URL是“api/batch”,必須把它添加在預設的API路由之前

Using async & await in .NET 4.5 makes the implementation of BatchHandler fairly straight-forward. All we need is an in-memory HttpServer which uses our existing configuration, so that the batched requests hit the exact same endpoints as requests from the Internet:
利用.NET 4.5中的async和await可以很直接地構造BatchHandler實現。我們所需要的只是一個放在記憶體中的HttpServer,它使用當前配置,以便當請求來自Internet時,需要分批的請求會找到完全相同的端點:

public class BatchHandler : HttpMessageHandler{    HttpMessageInvoker _server; 
public BatchHandler(HttpConfiguration config) { _server = new HttpMessageInvoker(new HttpServer(config)); }
protected override async Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { // Return 400 for the wrong MIME type // 對於錯誤的MIME類型,返回400 if ("multipart/batch" != request.Content.Headers.ContentType.MediaType) { return request.CreateResponse(HttpStatusCode.BadRequest); }
// Start a multipart response // 啟動一個multipart響應 var outerContent = new MultipartContent("batch"); var outerResp = request.CreateResponse(); outerResp.Content = outerContent;
// Read the multipart request // 讀取multipart請求 var multipart = await request.Content.ReadAsMultipartAsync(); foreach (var httpContent in multipart.Contents) { HttpResponseMessage innerResp = null; try { // Decode the request object // 解碼請求對象 var innerReq = await httpContent.ReadAsHttpRequestMessageAsync();
// Send the request through the pipeline // 通過管線發送請求 innerResp = await _server.SendAsync( innerReq, cancellationToken ); } catch (Exception) { // If exceptions are thrown, send back generic 400 // 如果拋出異常,回傳泛型的400 innerResp = new HttpResponseMessage( HttpStatusCode.BadRequest ); }
// Wrap the response in a message content and put it // into the multipart response // 在訊息內容中封裝響應,並把它放入multipart響應 outerContent.Add(new HttpMessageContent(innerResp)); }
return outerResp; }}

Now we have an endpoint that we can send multipart/batch requests to, which are assumed to be HTTP request objects (anything which isn't is going to yield a 400).
現在,我們擁有了一個端點,我們能夠把multipart/batch請求發送給它,假設這些請求都是HTTP請求對象(任何不是HTTP請求的對象都會產生一個400狀態代碼)。

On the client side, we make a multipart request and push requests into the multipart batch, one at a time:
在用戶端,我們形成了一個multipart請求,並把請求推入multipart batch,每次壓入一個請求:

var client = new HttpClient();var batchRequest = new HttpRequestMessage(    HttpMethod.Post,    "http://localhost/api/batch"); 
var batchContent = new MultipartContent("batch");batchRequest.Content = batchContent;
batchContent.Add( new HttpMessageContent( new HttpRequestMessage( HttpMethod.Get, "http://localhost/api/values" ) ));
batchContent.Add( new HttpMessageContent( new HttpRequestMessage( HttpMethod.Get, "http://localhost/foo/bar" ) ));
batchContent.Add( new HttpMessageContent( new HttpRequestMessage( HttpMethod.Get, "http://localhost/api/values/1" ) ));

In a console application, we can log both the request and response with code like this:
在一個控制台應用程式中,我們可以用以下代碼對請求和響應時行日誌:

using (Stream stdout = Console.OpenStandardOutput()){    Console.WriteLine("<<< REQUEST >>>");    Console.WriteLine();    Console.WriteLine(batchRequest);    Console.WriteLine();
batchContent.CopyToAsync(stdout).Wait();
Console.WriteLine(); var batchResponse = client.SendAsync(batchRequest).Result; Console.WriteLine("<<< RESPONSE >>>"); Console.WriteLine(); Console.WriteLine(batchResponse); Console.WriteLine(); batchResponse.Content.CopyToAsync(stdout).Wait(); Console.WriteLine(); Console.WriteLine();}

When I run this console application, I see output similar to this:
當運行這個控制台應用程式時,會看到輸出類似於這樣:

<<< REQUEST >>> 
Method: POST,RequestUri: 'http://localhost/api/batch',Version: 1.1,Content: System.Net.Http.MultipartContent,Headers:{ Content-Type: multipart/batch; boundary="3bc5bd67-3517-4cd0-bcdd-9d23f3850402"}
--3bc5bd67-3517-4cd0-bcdd-9d23f3850402Content-Type: application/http; msgtype=request
GET /api/values HTTP/1.1Host: localhost
--3bc5bd67-3517-4cd0-bcdd-9d23f3850402Content-Type: application/http; msgtype=requestGET /foo/bar HTTP/1.1Host: localhost
--3bc5bd67-3517-4cd0-bcdd-9d23f3850402Content-Type: application/http; msgtype=request
GET /api/values/1 HTTP/1.1Host: localhost
--3bc5bd67-3517-4cd0-bcdd-9d23f3850402--<<< RESPONSE >>>
StatusCode: 200,ReasonPhrase: 'OK',Version: 1.1,Content: System.Net.Http.StreamContent,Headers:{ Pragma: no-cache Cache-Control: no-cache Date: Thu, 21 Jun 2012 00:21:40 GMT Server: Microsoft-IIS/8.0 X-AspNet-Version: 4.0.30319 X-Powered-By: ASP.NET Content-Length: 658 Content-Type: multipart/batch Expires: -1}
--3d1ba137-ea6a-40d9-8e34-1b8812394baaContent-Type: application/http; msgtype=response
HTTP/1.1 200 OKContent-Type: application/json; charset=utf-8
["Hello","world!"]
--3d1ba137-ea6a-40d9-8e34-1b8812394baaContent-Type: application/http; msgtype=response
HTTP/1.1 404 Not FoundContent-Type: application/json; charset=utf-8
{"Message":"No HTTP resource was found that matches the request URI 'http://localhost/foo/bar'."}
--3d1ba137-ea6a-40d9-8e34-1b8812394baaContent-Type: application/http; msgtype=response
HTTP/1.1 200 OKContent-Type: application/json; charset=utf-8
"world!"--3d1ba137-ea6a-40d9-8e34-1b8812394baa--

As you can see, our batch was successfully run, and the results show what we'd expected (the two real API calls returned back 200 with their data, and the bogus request we threw in the middle returns back a 404).
正如我們所看到的,批處理成功地運行了,並且顯示了我們所期望的結果(兩個真正的API調用返回了帶有其資料的200狀態代碼,而在中間壓入的偽造請求返回了404狀態代碼)。

看完此文如果覺得有所收穫,請給個推薦

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.