ASP.NET Web API下Controller激活
一、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类型必须具有一个默认构造函数雅思答案 www.jamo123.com
二、HttpController的释放
我们知道作为自定义HttpController默认基类的ApiController类型实现了IDispoable接口,资源释放工作可以通过调用实现的Dispose方法来完成,那么这个方法是在什么时候执行的呢?除此之外,我们知道表示请求的HttpRequestMessage类型具有一个字典类型的属性Properties,我们可以利用它将任何一个对象附加到一个HttpRequestMessage对象上,如果这些附加对象需要实施资源释放操作,这些操作又是在什么时候被执行的呢?
实际上HttpRequestMessage通过Properties属性表示的属性字典为需要释放的资源预留了存储空间,对应的Key为“MS_DisposableRequestResources”,对应的值是一个List的对象。我们可以调用HttpRequestMessage具有如下定义的扩展方法GetResourcesForDisposal得到这个列表,也可以调用扩展方法RegisterForDispose将一个或者多个类型实现了IDisposable接口的对象放到这个列表中。
1: public static class HttpRequestMessageExtensions
2: {
3: //其他成员
4: public static IEnumerable GetResourcesForDisposal(this HttpRequestMessage request);
5:
6: public static void RegisterForDispose(this HttpRequestMessage request, IEnumerable 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会负责完成如下三项与资源释放有关的工作托福答案 www.yztrans.com
调用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自身的释放和对附加到属性字典中资源的释放 www.yzyxedu.com
我们不妨通过一个简单的实例来演示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下Controller的激活与释放流程
通过<ASP.NET Web API的Controller是如何被创建的?>我们已经对HttpController激活系统的核心对象有了深刻的了解,这些对象包括用于解析程序集和有效Http ...
- ASP.NET Web API下的HttpController激活:程序集的解析
ASP.NET Web API下的HttpController激活:程序集的解析 HttpController的激活是由处于消息处理管道尾端的HttpRoutingDispatcher来完成的,具体来 ...
- 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中的Controller
虽然通过Visual Studio向导在ASP.NET Web API项目中创建的 Controller类型默认派生与抽象类型ApiController,但是ASP.NET Web API框架本身只要 ...
- [ASP.NET Web API]如何Host定义在独立程序集中的Controller
通过<ASP.NET Web API的Controller是如何被创建的?>的介绍我们知道默认ASP.NET Web API在Self Host寄宿模式下用于解析程序集的Assemblie ...
- Self Host模式下的ASP. NET Web API是如何进行请求的监听与处理的?
构成ASP.NET Web API核心框架的消息处理管道既不关心请求消息来源于何处,也不需要考虑响应消息归于何方.当我们采用Web Host模式将一个ASP.NET应用作为目标Web API的宿主时, ...
- 目标HttpController在ASP.NET Web API中是如何被激活的:目标HttpController的创建
目标HttpController在ASP.NET Web API中是如何被激活的:目标HttpController的创建 通过上面的介绍我们知道利用HttpControllerSelector可以根据 ...
- ASP.NET Web API的核心对象:HttpController
ASP.NET Web API的核心对象:HttpController 对于ASP.NET Web API来说,所谓的Web API定义在继承自ApiController的类中,可能ApiContro ...
随机推荐
- 我眼中的 Oracle 性能优化
恒生技术之眼 作者 林景忠 大家对于一个业务系统的运行关心有如下几个方面:功能性.稳定性.效率.安全性.而一个系统的性能有包含了网络性能.应用性能.中间件性能.数据库性能等等. 今天从数据库性能的角度 ...
- uva11549 Floyd判圈法
题意: 给两个数n, k,每次将k平方取k的前n位,问所有出现过的数的最大值 原来这就是floyd判圈法.. #include<cstdio> #include<cstdlib> ...
- 如何制作iso文件
UltraISO 9.6.2.3059中文完美破解安装版 http://www.upantool.com/qidong/2011/UltraISO_v9.5.0.2800.html 软碟通v9.6.2 ...
- dreamvc框架(一)ioc容器的集成
我的dreamvc框架最终写得差点儿相同了,借鉴了非常多开源框架,SpringMVC.Struts2等,眼下放在github上面.地址请猛戳我 写得差点儿相同了,是要写一个总结,把自己当时的思路记录下 ...
- HDU--5280(dp或枚举)
官方题解: 这个题有非常多O(n2)的算法.这里说一种:枚举每个区间,在枚举区间的同一时候维护区间内的最小值和区间和,将最小值与P的大小进行比較,贪心地取最大值就可以.注意若枚举到的区间是整个数组,则 ...
- 如何在word2007中并排查看对比显示两个文档
使用word编辑或修改文件时,有时会需要对两个文档进行对比,此时就应该使用并排查看功能. 点击“视图”菜单中的“并排查看” 所打开的两个文档就会同时打开,并排显示 可点击“同步滚动”设置或取消同步滚动
- 【UVA】11732 - strcmp() Anyone?
一開始不知道这样的一维建树方法. 每次一层用一个链指向下一层最左边的结点,之后每一层用一个链表串联全部的结点,这样就建树成功了. 14328524 11732 option=com_onlinejud ...
- hdu 4622 Reincarnation(后缀数组)
hdu 4622 Reincarnation 题意:还是比较容易理解,给出一个字符串,最长2000,q个询问,每次询问[l,r]区间内有多少个不同的字串. (为了与论文解释统一,这里解题思路里sa数组 ...
- javascript高级培训课程(一)
执行上下文 可执行代码类型-- 执行上下文类型 全局代码-- 全局上下文 函数代码-- 函数上下文 eval代码 -- eval上下文 arguments 超出传入参数个数的index 与形参不 ...
- css考核点整理(六)-水平居中定位的几种方式
定宽 text-align: center 父容器position:relative:子容器 position:absolute;left:50%; margin-left: 宽度/2 .Ce ...