对HttpModule的理解

在一次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的生命周期的图,可以看出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 。
 
结束语:如有错误,请批评指正。

参考文献:
【1】httpModules与httpHandlers之httpModules
【2】HttpApplication的认识与加深理解
【3】一点一点学ASP.NET之基础概念——HttpModule
【4】HttpHandler Factory
【5】ASP.NET Process Model之一:IIS 和 ASP.NET ISAPI

posted @ 2013-03-12 16:45  Charles-China  阅读(627)  评论(1编辑  收藏  举报