原文:【ASP.NET Web API教程】5.4 ASP.NET Web API批处理器

注:本文是【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-9d23f3850402
Content-Type: application/http; msgtype=request

GET /api/values HTTP/1.1
Host: localhost

--3bc5bd67-3517-4cd0-bcdd-9d23f3850402
Content-Type: application/http; msgtype=request
GET /foo/bar HTTP/1.1
Host: localhost

--3bc5bd67-3517-4cd0-bcdd-9d23f3850402
Content-Type: application/http; msgtype=request

GET /api/values/1 HTTP/1.1
Host: 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-1b8812394baa
Content-Type: application/http; msgtype=response

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

["Hello","world!"]

--3d1ba137-ea6a-40d9-8e34-1b8812394baa
Content-Type: application/http; msgtype=response

HTTP/1.1 404 Not Found
Content-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-1b8812394baa
Content-Type: application/http; msgtype=response

HTTP/1.1 200 OK
Content-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状态码)。

看完此文如果觉得有所收获,请给个推荐

【ASP.NET Web API教程】5.4 ASP.NET Web API批处理器的更多相关文章

  1. 【ASP.NET Web API教程】2.4 创建Web API的帮助页面

    原文:[ASP.NET Web API教程]2.4 创建Web API的帮助页面 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. 2.4 ...

  2. 【ASP.NET Web API教程】2 创建各种Web API

    原文 [ASP.NET Web API教程]2 创建各种Web API Chapter 2: Creating Web APIs第2章 创建各种Web API 本文引自:http://www.asp. ...

  3. 【ASP.NET Web API教程】1 ASP.NET Web API入门

    原文 [ASP.NET Web API教程]1 ASP.NET Web API入门 Getting Started with ASP.NET Web API第1章 ASP.NET Web API入门 ...

  4. 【ASP.NET Web API教程】2.4 创建Web API的帮助页面[转]

    注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. 2.4 Creating a Help Page for a Web API2.4 创建W ...

  5. ASP.NET Core 入门教程 9、ASP.NET Core 中间件(Middleware)入门

    一.前言 1.本教程主要内容 ASP.NET Core 中间件介绍 通过自定义 ASP.NET Core 中间件实现请求验签 2.本教程环境信息 软件/环境 说明 操作系统 Windows 10 SD ...

  6. ASP.NET Core 入门教程 8、ASP.NET Core + Entity Framework Core 数据访问入门

    一.前言 1.本教程主要内容 ASP.NET Core MVC 集成 EF Core 介绍&操作步骤 ASP.NET Core MVC 使用 EF Core + Linq to Entity ...

  7. ASP.NET Core 入门教程 10、ASP.NET Core 日志记录(NLog)入门

    一.前言 1.本教程主要内容 ASP.NET Core + 内置日志组件记录控制台日志 ASP.NET Core + NLog 按天记录本地日志 ASP.NET Core + NLog 将日志按自定义 ...

  8. ASP.NET Core 入门教程 7、ASP.NET Core MVC 分部视图入门

    一.前言 1.本教程主要内容 ASP.NET Core MVC (Razor)分部视图简介 ASP.NET Core MVC (Razor)分部视图基础教程 ASP.NET Core MVC (Raz ...

  9. ASP.NET Core 入门教程 6、ASP.NET Core MVC 视图布局入门

    一.前言 1.本教程主要内容 ASP.NET Core MVC (Razor)视图母版页教程 ASP.NET Core MVC (Razor)带有Section的视图母版页教程 ASP.NET Cor ...

  10. ASP.NET Core 入门教程 5、ASP.NET Core MVC 视图传值入门

    一.前言 1.本教程主要内容 ASP.NET Core MVC 视图引擎(Razor)简介 ASP.NET Core MVC 视图(Razor)ViewData使用示例 ASP.NET Core MV ...

随机推荐

  1. 180China丨the Agency for Brand Engagement and Experience

    180China丨the Agency for Brand Engagement and Experience Welcome to 180. Welcome to Creativity. Thank ...

  2. Storm 配置图文解析

    Storm 配置图文解析 參考阅读:http://www.xiaofateng.com/? p=959 ============================== | sample-topology ...

  3. 使用ffmpeg将BMP图片编码为x264视频文件,将H264视频保存为BMP图片,yuv视频文件保存为图片的代码

    ffmpeg开源库,实现将bmp格式的图片编码成x264文件,并将编码好的H264文件解码保存为BMP文件. 实现将视频文件yuv格式保存的图片格式的測试,图像格式png,jpg, gif等等測试均O ...

  4. sencha touch笔记(5)——DataView组件(1)

    1.DataView组件可以显示列表,图像等等的组件或者元素,特别适用于数据仓库频繁更新的情况.比如像显示新闻或者微博等等的很多相同样式的组件的列表这种一次性从后台或者数据源拿取很多数据展示的样式.比 ...

  5. Spring整合Hibernate的步骤

    为什么要整合Hibernate?1.使用Spring的IOC功能管理SessionFactory对象 LocalSessionFactoryBean2.使用Spring管理Session对象  Hib ...

  6. SQL 教程

    SQL 教程 http://www.w3school.com.cn/sql/

  7. Ch02 从零开始实例学习6

    演练:理解Edit方法和Edit视图 原文链接:http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/exam ...

  8. POJ 2286 The Rotation Game 迭代搜索深度 + A* == IDA*

    感觉这样的算法还是比較局限的吧,反复搜索是一个不好的地方,并且须要高效的估值函数来进行强剪枝,这点比較困难. 迭代搜索深度是一个比較炫酷的搜索方式,只是有点拿时间换空间的感觉. 首先迭代深度比較搓的写 ...

  9. python模块介绍- binascii 二进制和ASCII转换

    python模块介绍-binascii二进制和ASCII转换 目录 项目简介 简介: Uu编码 Binhex编码 Base64编码 QP码 CRC校验和 二进制转换 其他实例 项目简介 Python中 ...

  10. LINQ to SQL的一些简单用法

    static void Main(string[] args) { var personList = new List<Person> { new Person() { PersonID= ...