ASP.NET Web API 管道模型
ASP.NET Web API 管道模型
前言
ASP.NET Web API是一个独立的框架,也有着自己的一套消息处理管道,不管是在WebHost宿主环境还是在SelfHost宿主环境请求和响应都是从消息管道经过的,这是必经之地,本篇就为大家简单的介绍一下ASP.NET Web API框架中的管道对象模型。
ASP.NET Web API路由、管道
- ASP.NET Web API 开篇介绍示例
- ASP.NET Web API 路由对象介绍
- ASP.NET Web API 管道模型
- ASP.NET Web API selfhost宿主环境中管道、路由
- ASP.NET Web API webhost宿主环境中管道、路由
管道模型介绍
HttpMessageHandler消息处理程序(基类)
public abstract class HttpMessageHandler : IDisposable
{
protected HttpMessageHandler();
public void Dispose();
protected virtual void Dispose(bool disposing);
protected internal abstract Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
}
上面的代码中定义的是消息处理程序基类,在管道中的每一个消息处理部分都是继承自它。
并且定义了一个会执行异步操作的SendAsync()方法,这个方法也是串联管道中各个消息处理程序的一个入口,但是并不是靠它来串联。
DelegatingHandler消息处理程序(基类)
public abstract class DelegatingHandler : HttpMessageHandler
{
protected DelegatingHandler();
protected DelegatingHandler(HttpMessageHandler innerHandler);
public HttpMessageHandler InnerHandler { get; set; } protected override void Dispose(bool disposing);
protected internal override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
}
这里的DelegatingHandler继承自HttpMessageHandler类型,而且DelegatingHandler也是抽象类型,DelegatingHandler类型并不是就是简单的继承,而是对基类进行了扩展,使之变成一个带指向箭头(对象引用)的对象类型也就是InnerHandler属性,InnerHandler属性的值就是在当前这个消息处理程序的下一个消息处理程序,DelegatingHandler类型对基类的扩展,HttpMessageHandler类型我感觉它的存在就是一个规范,从管道中的第一个处理程序开始一直到最后一个,除了最后一个消息处理程序,其他的都是DelegatingHandler类型的子类(当然也是HttpMessageHandler的子类),最后一个消息处理程序是直接继承自HttpMessageHandler类型,因为它是最后一个处理程序了不必要有指向下一个处理程序的属性,这种对职责的划分真的很优美,说不出好在哪就是觉得漂亮。
HttpServer消息处理程序(实现类-管道头)
public class HttpServer : DelegatingHandler
{
public HttpServer();
public HttpServer(HttpConfiguration configuration);
public HttpServer(HttpMessageHandler dispatcher);
public HttpServer(HttpConfiguration configuration, HttpMessageHandler dispatcher);
public HttpConfiguration Configuration { get; }
public HttpMessageHandler Dispatcher { get; } protected override void Dispose(bool disposing);
protected virtual void Initialize();
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
}
HttpServer类型继承自DelegatingHandler类型,是作为管道中第一个消息处理的,要说明的是重载的这些构造函数,如果只是采用默认的构造函数的话,HttpConfiguration类型的参数默认的就是实例化HttpConfiguration类型,而HttpMEssageHandler类型的参数默认的是实例化HttpRoutingDispatcher类型的消息处理器,并且是赋值到Dispatcher属性的,是作为管道中最后一个消息处理器的(真正的操作实际不是它,后面篇幅会有讲到)。
HttpRoutingDispatcher消息处理程序(实现类-管道尾)
public class HttpRoutingDispatcher : HttpMessageHandler
{
// Fields
private readonly HttpConfiguration _configuration;
private readonly HttpMessageInvoker _defaultInvoker; // Methods
public HttpRoutingDispatcher(HttpConfiguration configuration);
public HttpRoutingDispatcher(HttpConfiguration configuration, HttpMessageHandler defaultHandler);
private static void RemoveOptionalRoutingParameters(IDictionary<string, object> routeValueDictionary);
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
}
HttpRoutingDispatcher类型继承自HttpMessageHandler类型,上面也说到过它是作为在管道中最后一个消息处理器的,说是可以这么说,但是真正执行的却不是它,而是在执行重载的构造函数的时候会默认的生成HttpControllerDispatcher类型作为HttpMessageHandler类型的构造函数参数,这里就不对它进行过多的阐述了,后面的篇幅自然会说明的很详细。
下面我们来看一下ASP.NET Web API管道的大概示意图。
图1

(蓝色线条表示请求,红色线条表示响应)
这样的示意图说明的不是太清晰下面我们用《ASP.NET Web API 开篇介绍示例》中的SelfHost环境下的示例来演示一下,这样大家自然就会清楚这个流程了。
首先我们定义一个消息处理器类型命令为CustomDelegatingHandler,并且继承自DelegatingHandler类型。示例代码如下
代码1-1
public class CustomDelegatingHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
Console.WriteLine(request.RequestUri.OriginalString + "____" + request.Method.Method); Task<HttpResponseMessage> responseMessage = base.SendAsync(request, cancellationToken); Console.WriteLine(responseMessage.Result.RequestMessage.Method.Method); return responseMessage;
}
}
随之我们在SelfHost环境下的服务端在注册路由之后注册刚才我们新建的消息处理程序对象,示例代码如下:
代码1-2
static void Main(string[] args)
{
HttpSelfHostConfiguration selfHostConfiguration =
new HttpSelfHostConfiguration("http://localhost/selfhost");
using (HttpSelfHostServer selfHostServer = new HttpSelfHostServer(selfHostConfiguration))
{
selfHostServer.Configuration.Routes.MapHttpRoute(
"DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional });
RegistrationMessageHandler(selfHostServer.Configuration); selfHostServer.OpenAsync(); Console.WriteLine("服务器端服务监听已开启");
Console.Read();
} }
static void RegistrationMessageHandler(HttpConfiguration httpconfiguration)
{
httpconfiguration.MessageHandlers.Add(new HttpMessageHandlers.CustomDelegatingHandler());
}
在注册完毕,并且服务器已经启动开启请求监听,客户端也随之发出请求之后,我们再来看一下客户端发出的请求以及类型,如下图。
图2

这个时候我们再来看一下服务端管道处理情况,如下图。
图3

每一个红框圈中的部分都表示着一个请求和响应的流程跟图2中的所有请求是对应的,可以从代码1-1中就可以看出输出的内容。
如果说这样的示例并不不明显,不能让人很清楚明白的了解管道的执行过程以及顺序,那我们定义两个处理程序,并且修改代码1-1,示例代码如下:
代码1-3
public class CustomDelegatingHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
Console.WriteLine(this.GetType().Name + ":" + request.RequestUri.OriginalString + "____" + request.Method.Method); Task<HttpResponseMessage> responseMessage = base.SendAsync(request, cancellationToken); Console.WriteLine(this.GetType().Name + ":" + responseMessage.Result.RequestMessage.Method.Method); return responseMessage;
}
} public class CustomDelegatingHandler_1 : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
Console.WriteLine(this.GetType().Name + ":" + request.RequestUri.OriginalString + "____" + request.Method.Method); Task<HttpResponseMessage> responseMessage = base.SendAsync(request, cancellationToken); Console.WriteLine(this.GetType().Name + ":" + responseMessage.Result.RequestMessage.Method.Method); return responseMessage;
}
}
随之我们注册管理处理程序的地方也要新增一个消息处理程序,示例代码如下:
代码1-4
static void RegistrationMessageHandler(HttpConfiguration httpconfiguration)
{
httpconfiguration.MessageHandlers.Add(new HttpMessageHandlers.CustomDelegatingHandler());
httpconfiguration.MessageHandlers.Add(new HttpMessageHandlers.CustomDelegatingHandler_1());
}
这个时候按照图2之前的那段说明操作,再看一下服务端的管道处理情况,请求还是那些个请求,看下示意图如下:
图4

(红框部分的代表就是跟上面所说的一样,一个请求一个响应管道所对应的处理情况)
最后再看一下图5结合图4,这样更好更容易理解。
图5

作者:金源
出处:http://www.cnblogs.com/jin-yuan/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面
ASP.NET Web API 管道模型的更多相关文章
- ASP.NET Web API编程——模型验证与绑定
1.模型验证 使用特性约束模型属性 可以使用System.ComponentModel.DataAnnotations提供的特性来限制模型. 例如,Required特性表示字段值不能为空,Range特 ...
- ASP.NET WEB API 自定义模型校验过滤器
对外公开WEB接口时,对模型校验是常见的安全常识,常见的写法是在controller中判断ModelState.IsValid,以注册用户API为例. Model: public class Regi ...
- ASP.NET Web API WebHost宿主环境中管道、路由
ASP.NET Web API WebHost宿主环境中管道.路由 前言 上篇中说到ASP.NET Web API框架在SelfHost环境中管道.路由的一个形态,本篇就来说明一下在WebHost环境 ...
- ASP.NET Web API Selfhost宿主环境中管道、路由
ASP.NET Web API Selfhost宿主环境中管道.路由 前言 前面的几个篇幅对Web API中的路由和管道进行了简单的介绍并没有详细的去说明一些什么,然而ASP.NET Web API这 ...
- ASP.NET Web API 控制器创建过程(一)
ASP.NET Web API 控制器创建过程(一) 前言 在前面对管道.路由有了基础的了解过后,本篇将带大家一起学习一下在ASP.NET Web API中控制器的创建过程,这过程分为几个部分下面的内 ...
- ASP.NET Web API 路由对象介绍
ASP.NET Web API 路由对象介绍 前言 在ASP.NET.ASP.NET MVC和ASP.NET Web API这些框架中都会发现有路由的身影,它们的原理都差不多,只不过在不同的环境下作了 ...
- ASP.NET Web API模型验证以及异常处理方式
ASP.NET Web API的模型验证与ASP.NET MVC一样,都使用System.ComponentModel.DataAnnotations. 具体来说,比如有:[Required(Erro ...
- Self Host模式下的ASP. NET Web API是如何进行请求的监听与处理的?
构成ASP.NET Web API核心框架的消息处理管道既不关心请求消息来源于何处,也不需要考虑响应消息归于何方.当我们采用Web Host模式将一个ASP.NET应用作为目标Web API的宿主时, ...
- ASP.NET Web API路由系统:路由系统的几个核心类型
虽然ASP.NET Web API框架采用与ASP.NET MVC框架类似的管道式设计,但是ASP.NET Web API管道的核心部分(定义在程序集System.Web.Http.dll中)已经移除 ...
随机推荐
- PHP 5.6 编译安装选项说明
`configure' configures this package to adapt to many kinds of systems. Usage: ./configure [OPTION].. ...
- 解决PHP-问题:Class 'SimpleXMLElement' not found in
1.问题 在ubuntu 16.10中,学习PHP,学习到PHP如何生成XML文件时候,碰到了这个问题: PHP Fatal error: Class 'ClassName\SimpleXMLElem ...
- Vue + Webpack + Vue-loader 系列教程(1)功能介绍篇
原文地址:https://lvyongbo.gitbooks.io/vue-loader/content/ Vue-loader 是什么? vue-loader 是一个加载器,能把如下格式的 Vue ...
- 前端学HTTP之内容协商
前面的话 一个URL常常需要代表若干不同的资源.例如那种需要以多种语言提供其内容的网站站点.如果某个站点有说法语的和说英语的两种用户,它可能想用这两种语言提供网站站点信息.理想情况下,服务器应当向英语 ...
- Android 剪贴板详解
版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Clipboard 如本文有助于你理解 Android 剪贴板,不妨给我一个 Star.对于码农而言, ...
- SDWebImage源码解读之SDWebImageCache(上)
第五篇 前言 本篇主要讲解图片缓存类的知识,虽然只涉及了图片方面的缓存的设计,但思想同样适用于别的方面的设计.在架构上来说,缓存算是存储设计的一部分.我们把各种不同的存储内容按照功能进行切割后,图片缓 ...
- angularjs 依赖注入--自己学着实现
在用angular依赖注入时,感觉很好用,他的出现是 为了"削减计算机程序的耦合问题" ,我怀着敬畏与好奇的心情,轻轻的走进了angular源码,看看他到底是怎么实现的,我也想写个 ...
- Spark读写Hbase的二种方式对比
作者:Syn良子 出处:http://www.cnblogs.com/cssdongl 转载请注明出处 一.传统方式 这种方式就是常用的TableInputFormat和TableOutputForm ...
- Hibernate中事务的隔离级别设置
Hibernate中事务的隔离级别,如下方法分别为1/2/4/8. 在Hibernate配置文件中设置,设置代码如下
- TYPESDK手游聚合SDK服务端设计思路与架构之一:应用场景分析
TYPESDK 服务端设计思路与架构之一:应用场景分析 作为一个渠道SDK统一接入框架,TYPESDK从一开始,所面对的需求场景就是多款游戏,通过一个统一的SDK服务端,能够同时接入几十个甚至几百个各 ...