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中)已经移除 ...
随机推荐
- 本人提供微软系.NET技术顾问服务,欢迎企业咨询!
背景: 1:目前微软系.NET技术高端人才缺少. 2:企业很难直接招到高端技术人才. 3:本人提供.NET技术顾问,保障你的产品或项目在正确的技术方向. 技术顾问服务 硬服务项: 1:提供技术.决策. ...
- iOS开源项目周报0105
由OpenDigg 出品的iOS开源项目周报第四期来啦.我们的iOS开源周报集合了OpenDigg一周来新收录的优质的iOS开发方面的开源项目,方便iOS开发人员便捷的找到自己需要的项目工具等. He ...
- BootStrap_02之全局样式及组件
1.BootStrap指定的四种屏幕尺寸: ①超大PC屏幕--lg(large):w>=1200px: ②中等PC屏幕--md(medium):1200px>w>=992px: ③P ...
- 神经网络、logistic回归等分类算法简单实现
最近在github上看到一个很有趣的项目,通过文本训练可以让计算机写出特定风格的文章,有人就专门写了一个小项目生成汪峰风格的歌词.看完后有一些自己的小想法,也想做一个玩儿一玩儿.用到的原理是深度学习里 ...
- 就这么漂来漂去---一个毕业三个月的java程序员的裸辞风波
注:这并不是一篇技术文章,而是记录了我这几个月经历的入职,裸辞,找工作的心路历程,简单介绍一个博主的情况,我是16年毕业生,校招进了一家北京的公司,java开发,和很多年轻人一样,干了一段时间,我发现 ...
- 代码的坏味道(19)——狎昵关系(Inappropriate Intimacy)
坏味道--狎昵关系(Inappropriate Intimacy) 特征 一个类大量使用另一个类的内部字段和方法. 问题原因 类和类之间应该尽量少的感知彼此(减少耦合).这样的类更容易维护和复用. 解 ...
- ActionContext.getContext().getSession()
ActionContext.getContext().getSession() 获取的是session,然后用put存入相应的值,只要在session有效状态下,这个值一直可用 ActionConte ...
- 最近在玩linux时 yum 遇到了问题
主要是软件源出现了问题 我做的方式可能比较粗暴 ls -l /etc/yum.repos.d/ /*查看软件源*/ rm -rf /etc/yum.repos.d/ /*全删了*/ m ...
- WebAPI
WebAPI的Host OWIN IIS WebAPI 的handler和Filter有啥区别? WebAPI 常用 Filters Exception Filter Timer Filter Lo ...
- 用apt-file解决找不到头文件的问题
在编译C语言的开源项目的时候,经常会出现头文件找不到的问题. 解决这类问题有一个特别好用的工具apt-file 1.在ubuntu下安装 sudo apt install apt-file 2.更新索 ...