总体介绍ASP.NET Web API下Controller的激活与释放流程
通过《ASP.NET Web API的Controller是如何被创建的?》我们已经对HttpController激活系统的核心对象有了深刻的了解,这些对象包括用于解析程序集和有效HttpController类型的AssembliesResolver和HttpControllerTypeResolver、根据请求完整目标HttpController选择的HttpControllerSelector、负责激活目标HttpController实例的HttpControllerActivator、以及作为IoC容器的DependencyResolver。[本文已经同步到《How ASP.NET Web API Works?》]
一、HttpController激活流程

对于组成ASP.NET Web API核心框架的消息处理管道来说,处于末端的HttpMessageHandler是一个HttpRoutingDispatcher对象。当它完成路由解析工作之后(HttpRoutingDispatcher的路由解析只发生在Self Host寄宿模式下,对于Web Host寄宿模式来说,路由解析工作是由ASP.NET路由系统来完成的),在默认情况下它会将请求传递给一个HttpControllerDispatcher对象。
HttpControllerDispatcher实现了目标HttpController对象的激活与执行,并将代表执行结果的HttpResponseMessage对象返回给HttpRoutingDispatcher对象,后者将此HttpResponseMessage回传给消息管道进行相应处理后最终完成对请求的响应。
右图所示的UML体现了激活HttpController的整个流程。当HttpControllerDispatcher接管请求之后,它会获取注册的HttpControllerSelector对象,并调用其SelectController方法得到描述目标HttpController的HttpControllerDescriptor对象。
默认注册的HttpControllerSelector是一个DefaultHttpControllerSelector对象,后者借助于注册的HttpControllerTypeResolver对象得到所有HttpController类型,进而创建一个描述这些HttpController的HttpControllerDescriptor对象与HttpController名称之间的映射关系。当它的SelectController方法被执行后,它只需要根据请求携带的HttpRouteData对象获取目标HttpController的名称,并从此映射关系中选择对应的HttpControllerDescriptor即可。
HttpControllerDispatcher接下来调用这个HttpControllerDescriptor对象的CreateController方法得到激活的HttpController对象。对于这个HttpControllerDescriptor对象来说,当它的CreateController方法被调用之后,它会获取注册的HttpControllerActivator对象,并调用其Create方法实现针对目标HttpController对象的激活并将激活的对象返回。
默认注册的DefaultHttpControllerActivator对象会利用注册的DependencyResolver根据HttpController类型去获取代表目标HttpController实例的对象。如果后者返回一个具体的HttpController对象,该对象将直接作为方法的返回值,否则DefaultHttpControllerActivator直接采用反射的形式创建目标HttpController对象并返回。
由于默认注册的DependencyResolver是一个EmptyResolver对象,由它返回的HttpController对象总是Null,所以在默认情况下激活的HttpController对象总是以反射的形式创建的。正因为如此,我们定义的HttpController类型必须具有一个默认构造函数。
二、HttpController的释放
我们知道作为自定义HttpController默认基类的ApiController类型实现了IDispoable接口,资源释放工作可以通过调用实现的Dispose方法来完成,那么这个方法是在什么时候执行的呢?除此之外,我们知道表示请求的HttpRequestMessage类型具有一个字典类型的属性Properties,我们可以利用它将任何一个对象附加到一个HttpRequestMessage对象上,如果这些附加对象需要实施资源释放操作,这些操作又是在什么时候被执行的呢?
实际上HttpRequestMessage通过Properties属性表示的属性字典为需要释放的资源预留了存储空间,对应的Key为“MS_DisposableRequestResources”,对应的值是一个List<IDisposable>的对象。我们可以调用HttpRequestMessage具有如下定义的扩展方法GetResourcesForDisposal得到这个列表,也可以调用扩展方法RegisterForDispose将一个或者多个类型实现了IDisposable接口的对象放到这个列表中。
1: public static class HttpRequestMessageExtensions
2: {
3: //其他成员
4: public static IEnumerable<IDisposable> GetResourcesForDisposal(this HttpRequestMessage request);
5:
6: public static void RegisterForDispose(this HttpRequestMessage request, IEnumerable<IDisposable> resources);
7: public static void RegisterForDispose(this HttpRequestMessage request,IDisposable resource);
8:
9: public static void DisposeRequestResources(this HttpRequestMessage request);
10: }
ASP.NET Web API还为释放这些附加到HttpRequestMessage上的对象定义了如上一个扩展方法DisposeRequestResources,那么这个方法究竟是在什么时候被调用的呢?
释放这些资源的时机取决于采用的寄宿模式。对于Web Host来说,ASP.NET Web API用于“处理请求、回复响应”的HttpMessageHandler管道是由HttpControllerHandler创建的,后者根据当前HTTP上下文创建一个表示当前请求的HttpRequestMessage对象并传入这个管道进行处理。在整个管道完成对请求的处理并最终对请求予以响应之后,HttpControllerHandler会负责完成如下三项与资源释放有关的工作。
- 调用HttpRequestMessage对象的扩展方法DisposeRequestResources释放附加在自身属性字典中的对象。
- 调用HttpRequestMessage对象的Dispose方法对请求消息本身作相应的释放工作。
- 调用返回的HttpResponseMessage对象对响应消息作相应的释放工作。
对于Self Host来说,通过《Self Host模式下的ASP. NET Web API是如何进行请求的监听与处理的?》的介绍我们知道请求的监听、接收和响应是通过HttpBinding创建的信道栈来完成的。该信道栈处理的消息类型为HttpMessage,具体代表请求消息和响应消息的HttpMessage分别是对HttpRequestMessage和HttpResponseMessage对象的封装。WCF中表示消息的Message本身就是一个需要最终被释放的对象,在针对它的处理结束之后会调用其Close或者Dispose方法对它进行资源释放的工作。
当一个HttpMessage对象的Close或者Dispose方法被调用的时侯,被其封装的HttpRequestMessage或者HttpResponseMessage会相应地得到释放。对于请求消息来说,具体的资源释放工作包括针对HttpRequestMessage自身的释放和对附加到属性字典中资源的释放。
我们不妨通过一个简单的实例来演示Self Host寄宿模式下伴随着HttpMessage对象的释放对被封装的HttpRequestMessage对象的释放。我们在一个控制台应用中定义了如下三个需要被释放的类型Foo、Bar和Baz,它们共同的基类DisposableObject实现了IDisposable接口,并在实现Dispose方法中通过输出一段文字以确定具体的释放操作是否被执行。
1: public class DisposableObject : IDisposable
2: {
3: public void Dispose()
4: {
5: Console.WriteLine("{0}.Dispose()", this.GetType().Name);
6: }
7: }
8:
9: public class Foo : DisposableObject
10: {}
11:
12: public class Bar : DisposableObject
13: {}
14:
15: public class Baz : DisposableObject
16: {}
然后我们再Main方法中编写了如下一段简短的程序。我们分别创建了类型为Foo、Bar和Baz的三个对象,并通过调用扩展方法RegisterForDispose将它们注册到创建的HttpRequestMessage对象上。我们针对这个HttpRequestMessage对象利用反射的方式创建了一个HttpMessage对象,最终调用其Close方法对它作相应的释放工作。
1: class Program
2: {
3: static void Main(string[] args)
4: {
5: HttpRequestMessage request = new HttpRequestMessage();
6: request.RegisterForDispose(new Foo());
7: request.RegisterForDispose(new Bar());
8: request.RegisterForDispose(new Baz());
9:
10: Type httpMessageType = Type.GetType("System.Web.Http.SelfHost.Channels.HttpMessage, System.Web.Http.SelfHost");
11: Message httpMessage = (Message)Activator.CreateInstance(httpMessageType, new object[] { request });
12: httpMessage.Close();
13: }
14: }
我们运行这段程序后会控制台上得到如下的输出结果,由此可见通过调用扩展方法RegisterForDispose注册到某个HttpRequestMessage对象上的资源能够在它释放的时候得到释放。(S406)
1: Foo.Dispose()
2: Bar.Dispose()
3: Baz.Dispose()
对于ApiController来说,当它的ExecuteAsync方法被执行的时候,它会调用扩展方法RegisterForDispose将自己注册到代表当前请求的HttpRequestMessage对象上。毫无疑问,ApiController对象的释放会通过对这个HttpRequestMessage的释放来完成。
总体介绍ASP.NET Web API下Controller的激活与释放流程的更多相关文章
- ASP.NET Web API下的HttpController激活:程序集的解析
ASP.NET Web API下的HttpController激活:程序集的解析 HttpController的激活是由处于消息处理管道尾端的HttpRoutingDispatcher来完成的,具体来 ...
- ASP.NET Web API下Controller激活
一.HttpController激活流程 对于组成ASP.NET Web API核心框架的消息处理管道来说,处于末端的HttpMessageHandler是一个HttpRoutingDispatche ...
- 剖析Asp.Net Web API中HttpController的激活
在Asp.Net Web API中,请求的目标是定义在某个HttpController中的某个Action方法.当请求经过Asp.Net Web API消息处理管道到达管道"龙尾" ...
- ASP.NET Web API的Controller是如何被创建的?
Web API调用请求的目标是定义在某个HttpController类型中的某个Action方法,所以消息处理管道最终需要激活目标HttpController对象.调用请求的URI会携带目标HttpC ...
- How ASP.NET Web API 2.0 Works?[持续更新中…]
一.概述 RESTful Web API [Web标准篇]RESTful Web API [设计篇] 在一个空ASP.NET Web项目上创建一个ASP.NET Web API 2.0应用 二.路由 ...
- 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 Web API 对于我这个初学者来说ASP.NET Web API这个框架很陌生又熟悉着. 陌生的是ASP.NET Web API是一个全 ...
- Self Host模式下的ASP. NET Web API是如何进行请求的监听与处理的?
构成ASP.NET Web API核心框架的消息处理管道既不关心请求消息来源于何处,也不需要考虑响应消息归于何方.当我们采用Web Host模式将一个ASP.NET应用作为目标Web API的宿主时, ...
- [ASP.NET Web API]如何Host定义在独立程序集中的Controller
通过<ASP.NET Web API的Controller是如何被创建的?>的介绍我们知道默认ASP.NET Web API在Self Host寄宿模式下用于解析程序集的Assemblie ...
随机推荐
- RSA密钥之C#格式与Java格式转换
前言 最近由于项目需求,服务端由c#编写,客户端由java编写.通信数据使用RSA非对称加密.但是java和c#生成的密钥格式是不一样的,所以需要转换格式才可以正常使用.网上搜到使用java进行格式转 ...
- UWP Composition API - 锁定列的FlexGrid
需求是第一列锁定,那么怎么让锁定列不跟着滚动条向做移动呢? 其实很简单,让锁定列跟scrollviewer的滚动做反方向移动. 先看一下这个控件的模板,嗯,其实很简单,就是ListView的模板,不同 ...
- svn: how to set the executable bit on a file?
http://stackoverflow.com/questions/17846551/svn-how-to-set-the-executable-bit-on-a-file svn uses pro ...
- Greenplum安装
最近需要安装Greenplum测试一些东西,在安装过程中出现了许多问题,所以在这里将安装过程整理一下,主要参考<Greenplum企业应用实践>和http://jxzhfei.blog.5 ...
- 2016-1-29 图解HTTP(04)
第7章 确保Web安全的HTTPS 在HTTP协议中有可能存在信息窃听或身份伪装等安全问题.使用HTTPS通信机制可以有效的防止这些问题. 7.1 HTTP的缺点 ● 通信使用明文(不加密),内容可能 ...
- Ubuntu 树莓派2b交叉编译环境
在一个平台上生成另一个平台上的可执行代码.为什么要大费周折的进行交叉编译呢?一句话:不得已而为之.有时是因为目的平台上不允许或不能够安装所需要的编译器,而又需要这个编译器的某些特征:有时是因为目的平台 ...
- 2016-2017 ACM-ICPC Southwestern European Regional Programming Contest (SWERC 2016)
A. Within Arm's Reach 留坑. B. Bribing Eve 枚举经过$1$号点的所有直线,统计直线右侧的点数,旋转卡壳即可. 时间复杂度$O(n\log n)$. #includ ...
- 利用Simple-RTMP-Server(SRS)来进行直播
1.下载SRS 官方地址:http://www.ossrs.net/srs.release/releases/ 百度地址:http://pan.baidu.com/s/1kV8WQpx 2.编译安装S ...
- 弱省互测#0 t3
Case 1 题意 要求给出下面代码的答案然后构造输入. 给一个图, n 个点 m 条边 q 次询问,输出所有点对之间最大权值最小的路径. 题解 把每一个询问的输出看成一条边,建一棵最小生成树. Ca ...
- Linux上mongodb开机自启动
1.下载MongoDB 2.安装MongoDB(安装到/usr/local下) .tgz mongodb cd mongodb mkdir db mkdir logs cd bin vi mongod ...