在一次interview中,被问及 HttpModules 与 HttpHandler ,似乎从一开始我就觉得这个东西应该是“网络攻城尸”他们去理解的。所以一直没有去了解这个东西。直到今天,在《ASP.NET MVC 1.0 高级编程》(菜鸟看天书)中看到这么一句话:”ASP.NET MVC 是构建在大家可能熟悉的构造或子系统上,如 HttpModules 和 HttpHandlers 。它的构建使用了与创建ASP.NET应用程序所使用的相同的API。“
于是,我觉得我是否应该了解下这个东西,他到底是什么。
以下是我几个小时的收获:(肯定会有些理解是不正确的,希望大虾予以指正)
首先,总结下参考文献【1】中ASP.NET对请求处理的过程:
当收到.aspx(razor视图 .cshtml 应该也是这个过程)请求时,会被inetinfo.exe的进程所截获,这个是www服务的一个进程,它判断下是否是.aspx(或是 .cshtml ),如果是则转交给ASPNET_ISAPI.DLL处理,至于为什么要转给它?因为IIS实际上只能处理.html的文件,IIS中的 Metadata database 维护着一个叫 ISAPI Extension Mapping 的数据表,他负责将不同类型的源(Resource)映射到不同的 ISAPI Extension上。
(需要说的是,IIS服务与ASPNET_ISAPI.DLL都寄存在inetinfo.exe中。之前我不知道寄存是什么意思,凭猜测 搜索下 register ,我想我更愿意将其翻译成 注册 )
然后ASPNET_ISAPI.DLL 将通过管道(http pipeLine)(管道?就是一组 HttpModules 与 HttpHandler 组成,为什么 HttpHandler 不是复数形式,因为每次清楚可能会有多个HttpModule进行预处理,但只会调用一个 HttpHandler )将请求发送给ASPNET_WP.exe(我想这是IIS 5.1中的进程,IIS 6.0及以上是 w3wp.exe,它是运行.net程序的托管环境,.net CLR 寄存于此),通过该进程中的 HttpRuntime 来处理这个请求,并返回结果给客户端。
说道标题中的HttpModule,这才真正出现。HttpModules到底在实际应用中有什么用呢?说笼统一点,那就是能干预在
客户端发送请求之后 与 服务器响应之前 的处理。那到底有哪些可用的方法呢?我截个图(HttpModule的生命周期):
在讨论这幅图之前,我想加点内容,摘抄 参考文献【1】中的内容:
.NET framwork 处理Http请求的过程:
http request --> inetinfo.exe --> aspnet_isapi.dll --> aspnet_wp.exe(w3wp.exe) --> Http Runtime --> HttpModule Factory --> HttpModule --> HttpHandler Factory --> HttpHandler --> HttpHandler.ProcessRequst()
如上所说,aspnet_isapi.dll 寄存在 inetinfo.exe 中,.net 的 CLR 都寄存在 w3wp.exe 中,我是不是就可以认为 上面 aspnet_isapi.dll 归于 inetinfo.exe, 从HTTP Runtime 及 其后的过程都归于 w3wp.exe 中(个人见解,如果差错,请批评指正),如下所示:
http request --> inetinfo.exe【aspnet_isapi.dll 】--> aspnet_wp.exe(w3wp.exe)【Http Runtime --> HttpModule Factory --> HttpModule --> HttpHandler Factory --> HttpHandler --> HttpHandler.ProcessRequst() 】
可是那么些 Factory 又是些什么东西,有什么用?(参见 参考文献【2】)
我这里有个基本的理解:
HttpRuntime 找到 HttpModule Factory 问:我给你的URL请求对应的是哪个虚拟目录啊?你想要哪个HttpApplication来处理这个请求啊?
HttpFactory 收到这样的质问,立马采取措施:先找到 对应的虚拟目录吧,好,找到了。然后去对象池里面找 HttpApplication,没有就创建一个对象,然后把这个对象给HttpRuntime.
然后初始化,其中就有 InitModules(); 初始化 Http 模块。
当请求经过 多个 Http 模块的预处理之后,移交给 HttpHandler【将在那一篇文章中出现】 处理,然后再通过HttpModule返回结果给客户端-------> 这就是管道:
那么怎么编写一个自己的HttpModule呢?当然的实现IHttpModule接口。如下所示:
public class MyModule: IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest+=new EventHandler(context_BeginRequst);
}
void context_BeginRequst(object sender,EventArgs e)
{
HttpApplication ha=(HttpApplication)sender;
ha.Response.Write(ha.Context.Request.Url.ToString());//在每个页面输出当前请求的地址
}
public void Dispose() { }
}
代码是写完了,可是自己的这个Http模块怎么能够注册到系统里面去呢?
<system.web>
<httpModules>
<add name="MyModule" type="myWeb.MyModule,myWeb"/>
</httpModules>
</system.web>
type有两部分组成,前半部分是命名空间和类名组成的全名,后半部分是程序集名称,如果类是直接放在App_Code文件夹中,那程序名称是App_Code
上面的例子,开始请求时就往页面返回值,那么之后的操作都将不能进行。如果注册 EndRequest 事件,则可以在正常显示页面的情况下,输出自定义数据。
如果是使用MVC项目,我们可以查看下 Global 文件:
是不是可以说明 MVC 确实是 建立在 HttpModules 、HttpHadler 上呢?
因为 MvcApplication 继承 HttpApplication , 而 HttpApplication 继承了 IHttpHandler 。
结束语:如有错误,请批评指正