[Web API] Web API 2 深入系列(2) 消息管道
目录
HttpMessageHandler
Web Host模式处理过程
Self Host模式处理过程
HttpMessageHandler
Web API处理管道由一系列HttpMessageHandler组成
public abstract class HttpMessageHandler : IDisposable
{
protected internal abstract Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
protected virtual void Dispose(bool disposing)
public void Dispose()
}
而一般在管道中,我们使用DelegatingHandler
public abstract class DelegatingHandler : HttpMessageHandler
{
public HttpMessageHandler InnerHandler { get; set; }
protected internal override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return this.innerHandler.SendAsync(request, cancellationToken);
}
}
头部是HttpServer
public class HttpServer : DelegatingHandler
{
public HttpMessageHandler Dispatcher { get; }
public HttpConfiguration Configuration { get; }
protected virtual void Initialize()
{
this.InnerHandler = HttpClientFactory.CreatePipeline(this._dispatcher, (IEnumerable<DelegatingHandler>) this._configuration.MessageHandlers);
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
this.EnsureInitialized();
return await base.SendAsync(request, cancellationToken);
}
}
其中Dispatcher就是管道的尾部
默认为HttpRoutingDispatcher
public class HttpRoutingDispatcher : HttpMessageHandler
{
public HttpConfiguration Configuration { get; }
private readonly HttpMessageInvoker _defaultInvoker = new HttpControllerDispatcher(configuration);
public HttpRoutingDispatcher(HttpConfiguration configuration, HttpMessageHandler defaultHandler)
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
//1. Routing
IHttpRouteData routeData = request.GetRouteData();
if (routeData == null)
{
routeData = this._configuration.Routes.GetRouteData(request);
if (routeData != null)
request.SetRouteData(routeData);
}
//2. Dispatcher
this._defaultInvoker.SendAsync(request, cancellationToken);
}
}
实现Dispatcher(选择IHttpController)的对象默认为HttpControllerDispatcher
public class HttpControllerDispatcher : HttpMessageHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpControllerDescriptor controllerDescriptor = this.ControllerSelector.SelectController(request);
IHttpController controller = controllerDescriptor.CreateController(request);
return await controller.ExecuteAsync(controllerContext, cancellationToken);
}
}
验证管道
public class DemoController : ApiController
{
public IEnumerable<string> Get()
{
var cfg = new HttpConfiguration();
cfg.MessageHandlers.Add(new Handler1());
cfg.MessageHandlers.Add(new Handler1());
cfg.MessageHandlers.Add(new Handler1());
var server = new MyServer(cfg);
server.Initialize();//生成HttpMessageHandler链
return GetHandlers(server);
}
private IEnumerable<string> GetHandlers(MyServer server)
{
DelegatingHandler next = server;
yield return next.ToString();
while (next.InnerHandler != null)
{
yield return next.InnerHandler.ToString();
next = next.InnerHandler as DelegatingHandler;
if (next == null)
break;
}
}
}
class MyServer : HttpServer
{
public MyServer(HttpConfiguration cfg) : base(cfg) { }
public new void Initialize()//暴露Initialize方法
{
base.Initialize();
}
}
class Handler1 : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
浏览器中请求:

Web Host模式处理过程
上节我们说到HttpControllerHandler为Web Host下的处理程序.
public class HttpControllerHandler : HttpTaskAsyncHandler
{
private readonly HttpMessageInvoker _server = GlobalConfiguration.DefaultServer;
public override Task ProcessRequestAsync(HttpContext context)
{
response = await this._server.SendAsync(request, cancellationToken);
await response.Content.CopyToAsync(context.Response.OutputStream);
}
}
从上面的代码中我们看到
HttpControllerHandler实现的是异步HttpControllerHandler接口
在ProcessRequestAsync方法中 通过GlobalConfiguration.DefaultServer 启动了WebAPI管道
Self Host模式处理过程
Self Host目前可以说分为2种
- OWIN
- HttpBinding
本节重点说明一下传统方式的HttpBinding,WebAPI使用的Message为HttpMessage
通过Nuget可以非常方便的操作
Install-Package Microsoft.AspNet.WebApi.SelfHost
using (var server = new HttpSelfHostServer(new HttpSelfHostConfiguration("http://localhost:10000")))
{
server.Configuration.Routes.MapHttpRoute("default", "{controller}");
server.OpenAsync();
Console.Read();
}
接下来我们将定义一个HttpSelfHostServer来实现SelfHost
API是不是相比SelfHost更方便?
using (var server = new MyHttpSelfHostServer("http://localhost:10000"))
{
server.Configuration.Routes.MapHttpRoute("default", "{controller}");
server.OpenAsync();
Console.Read();
}
再看看我们具体的MyHttpSelfHostServer如何实现
public class MyHttpSelfHostServer : HttpServer
{
private string _url;
public MyHttpSelfHostServer(string url)
{
_url = url;
}
public async void OpenAsync()
{
var binding = new HttpBinding();
var listener = binding.BuildChannelListener<IReplyChannel>(new Uri(_url));
listener.Open();//开启监听
var reply = listener.AcceptChannel();
reply.Open();//开启通信通道
while (true)
{
var request = reply.ReceiveRequest();//接受到请求
//获取HttpRequestMessage
var method = request.RequestMessage.GetType().GetMethod("GetHttpRequestMessage");
var requestMessage = method.Invoke(request.RequestMessage, new object[] { true }) as HttpRequestMessage;
var response = await base.SendAsync(requestMessage, new CancellationTokenSource().Token);
request.Reply(CreateMessage(response));//回复消息
}
}
Message CreateMessage(HttpResponseMessage response)
{
var type = Type.GetType("System.Web.Http.SelfHost.Channels.HttpMessage,System.Web.Http.SelfHost");
return (Message)Activator.CreateInstance(type, response);
}
}
最后我们来请求一下地址:http://localhost:10000/Demo

备注:
文章中的代码并非完整,一般是经过自己精简后的.
本篇内容使用MarkDown语法编辑
首发地址:http://neverc.cnblogs.com/p/5949974.html
[Web API] Web API 2 深入系列(2) 消息管道的更多相关文章
- ASP.NET Web API - ASP.NET MVC 4 系列
Web API 项目是 Windows 通信接口(Windows Communication Foundation,WCF)团队及其用户激情下的产物,他们想与 HTTP 深度整合.WCF ...
- 如何用Baas快速在腾讯云上开发小程序-系列1:搭建API & WEB WebSocket 服务器
版权声明:本文由贺嘉 原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/221059001487422606 来源:腾云阁 h ...
- Java web与web gis学习笔记(二)——百度地图API调用
系列链接: Java web与web gis学习笔记(一)--Tomcat环境搭建 Java web与web gis学习笔记(二)--百度地图API调用 JavaWeb和WebGIS学习笔记(三)-- ...
- HTML5权威指南--Web Storage,本地数据库,本地缓存API,Web Sockets API,Geolocation API(简要学习笔记二)
1.Web Storage HTML5除了Canvas元素之外,还有一个非常重要的功能那就是客户端本地保存数据的Web Storage功能. 以前都是用cookies保存用户名等简单信息. 但是c ...
- 我所理解的RESTful Web API [Web标准篇]
REST不是一个标准,而是一种软件应用架构风格.基于SOAP的Web服务采用RPC架构,如果说RPC是一种面向操作的架构风格,而REST则是一种面向资源的架构风格.REST是目前业界更为推崇的构建新一 ...
- 重构Web Api程序(Api Controller和Entity)续篇
昨天有写总结<重构Web Api程序(Api Controller和Entity)>http://www.cnblogs.com/insus/p/4350111.html,把一些数据交换的 ...
- web api写api接口时返回
web api写api接口时默认返回的是把你的对象序列化后以XML形式返回,那么怎样才能让其返回为json呢,下面就介绍两种方法: 方法一:(改配置法) 找到Global.asax文件,在Applic ...
- Google Maps API Web Services
原文:Google Maps API Web Services 摘自:https://developers.google.com/maps/documentation/webservices/ Goo ...
- asp.net web api 构建api帮助文档
1 概要 创建ASP.NET Web Api 时模板自带Help Pages框架. 2 问题 1)使用VS创建Web Api项目时,模板将Help Pages框架自动集成到其中,使得Web Api项目 ...
随机推荐
- Android课程---远程服务器存储
在使用Volley进行获取数据时,需要事先准备环境:在libs里面导入一个Volley.jar包,在网上都有,可以下载下来导入,或者自己电脑上有DT的,自己合成一个包也行. WebActivity.j ...
- SQL Server 2008, 2008 R2, 2012 and 2014 完全支持TLS1.2加密传输
SQL Server 2008, 2008 R2, 2012 and 2014 完全支持TLS1.2加密传输 微软高兴地宣布所有主流SQL Server客户端驱动和SQL Server发行版已经支持T ...
- .NET开源OpenID和OAuth解决方案Thinktecture IdentityServer
现代的应用程序看起来像这样: 典型的交互操作包括: 浏览器与 web 应用程序进行通信 Web 应用程序与 web Api (有时是在他们自己的有时代表用户) 通信 基于浏览器的应用程序与 web A ...
- 【腾讯优测干货分享】越用越卡为哪般——如何降低App的待机内存(一)
本文来自于腾讯优测公众号(wxutest),未经作者同意,请勿转载,原文地址:http://mp.weixin.qq.com/s/1_FKMbi1enpcKMqto-o_FQ 作者:腾讯TMQ专项测试 ...
- 迷你MVVM框架 avalonjs 实现上的几个难点
经过两个星期的性能优化,avalon终于实现在一个页面绑定达到上万个的时候不卡顿的目标(angular的限制是2000).现在稍作休息,总结一下avalon遇到的一些难题. 首先是如何监控的问题.所有 ...
- .NET core for docker
本文描述下 .net core 在 docker 里面的玩法 首先按照官方文档先 拉取镜像 docker pull microsoft/dotnet:latest 然后就有了 dotnet 这个运行时 ...
- CSS 布局口诀
body { font-family: Segoe UI,"Microsoft YaHei", Georgia,Helvetica,Arial,sans-serif,宋体, PMi ...
- 基于Spring Mvc实现的Excel文件上传下载
最近工作遇到一个需求,需要下载excel模板,编辑后上传解析存储到数据库.因此为了更好的理解公司框架,我就自己先用spring mvc实现了一个样例. 基础框架 之前曾经介绍过一个最简单的spring ...
- 30个你必须记住的CSS选择符
所以你学会了基础的id,类和后代选择符,然后你就一直用它们了吗?如果是这样,你丢失了(css的)巨大的灵活性.在本文中提到的很多选择器属于CSS3规范的一部分,因此,只有在现代浏览器中才可使用. 1. ...
- js浏览器对象模型-BOM
bom browse object model 浏览器对象模型. 也就是window对象下面的东西. location 对象 window.location.href 表示打开窗口的路径. windo ...