前言
继上一篇理解并自定义HttpHandler后,有进行了HttpModule的进一步学习,本篇作为一个小结。
主要参考:Asp.Net 构架(HttpModule 介绍) - Part.3
目录
到底什么是HttpModule
Asp.net的事件分为三级:应用程序级、页面级和控件级。而HttpModule是通过在管道模型中对Asp.net的应用程序级事件进行
订阅,当应用程序级事件触发时调用HttpModule中对应的处理方法。也就是说HttpModule是订阅Asp.net应用程序级事件的入口,依附
于HttpApplication对象生命周期的各个事件。
系统内部的HttpModule
Asp.net内部很多功能都以HttpModule形式来实行,如Windows、Forms和PassPort认证、Session机制等。下面是部分的内部HttpModule及其作用。
名称 | 类型 | 功能 |
OutputCache | System.Web.Caching.OutputCacheModule | 页面级输出缓存 |
Session | System.Web.SessionState.SessionStateModule | Session状态管理 |
WindowsAuthentication | System.Web.Security.WindowsAuthenticationModule | 用集成Windows身份验证进行客户端验证 |
FormsAuthentication | System.Web.Security.FormsAuthenticationModule | 用基于Cookie的窗体身份验证进行客户端身份验证 |
PassportAuthentication | System.Web.Security.PassportAuthenticationModule | 用MS护照进行客户身份验证 |
RoleManager | System.Web.Security.RoleManagerModule | 管理当前用户角色 |
UrlAuthorization | System.Web.Security.UrlAuthorizationModule | 判断用户是否被授权访问某一URL |
FileAuthorization | System.Web.Security.FileAuthorizationModule | 判断用户是否被授权访问某一资源 |
AnonymousIdentification | System.Web.Security.AnonymousIdentificationModule | 管理Asp.Net应用程序中的匿名访问 |
Profile | System.Web.Profile.ProfileModule | 管理用户档案文件的创立 及相关事件 |
ErrorHandlerModule | System.Web.Mobile.ErrorHandlerModule | 捕捉异常,格式化错误提示字符,传递给客户端程序 |
配置HttpModule
自定义HttpModule跟自定义HttpHandler相似,都要在web.config文件中进行配置。形式如下:
1 <HttpModules>
2 <add name="MM" type="MyModule,MMAssembly"/>
3 </HttpModules>
1.type:跟HttpHandler中的一样,有两部分组成,第一部分是完整的类名(含命名空间名),第二部分是所在程序集名(不含.dll)。
2.name:HttpModule的名称,可以跟类名无关。通过HttpApplication对象的Modules属性获取
HttpModuleCollection,然后通过name获取对应的HttpModule对象;在Global.asax中通过方法名
ModuleName_EventName订阅HttpModule中的事件,这里为MM_具体的事件名,详细请见下面实例。
3.因为对于每个进入工作进程的请求都会经过各已配置的HttpModule的处理(因为HttpModule是订阅应用程序级事件的),所以配置文件中没有path和verb属性(不管是*.aspx还是*.ashx,请求方式为get还是post都会进行处理)。
注意:HttpModule的配置是无需像HttpHandler那样在IIS上进行配置的。
自定义HttpModule
每个HttpModule都继承System.Web.IHttpModule接口,并实现接口的Init(HttpApplication context)和Dispose()方法。如下:
public class MyModule:IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
void context_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.Write("BeginRequest");
}
public void Dispose()
{
}
}
Init():这个方法接受一个HttpApplication对象,HttpApplication代表了当
前的应用程序,我们需要在这个方法内订阅
HttpApplication对象暴露给客户端的事件。可见,这个方法仅仅是用来对事件进行订阅,而实际的事件处理程序,需要我们另外写方法。
Dispose():在垃圾回收前释放资源。
整个过程很好理解:
- 当站点第一个资源被访问的时候,Asp.Net会创建HttpApplication类的实例,它代表着站点应用程序,同时会创建所有在Web.Config中注册过的Module实例。
- 在创建Module实例的时候会调用Module的Init()方法。
- 在Init()方法内,对想要作出响应的HttpApplication暴露出的事件进行注册。(仅仅进行方法的简单注册,实际的方法需要另写)。
- HttpApplication在其应用程序周期中触发各类事件。
- 触发事件的时候调用Module在其Init()方法中注册过的方法。
关于委托可参考:委托与事件
Global.asax文件与 HttpModule
在asp.net中,Glabal不仅可以注册应用程序和Session事件,还可以注册Http Module暴露出的事件;不仅可以注册系统Module的事件,也可以注册我们自己义的Module暴露出的事件。在具体介绍之前,这里需要首先注意两点:
- 在每处理一个Http请求时,应用程序事件都会触发一遍,但是Application_Start和 Application_End 例外,它仅在第一个资源文件被访问时被触发。
- Http Module无法注册和响应Session事件,对于Session_Start 和 Session_End,只能通过Glabal.asax来处理。
继续上面的例子:
MyModule.cs文件
public class MyModule:IHttpModule
{
public event EventHandler ExposedEvent;//HttpModule事件,供Global.asax来订阅
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);//订阅HttpApplication的事件
}
void context_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.Write("BeginRequest");
OnExposedEvent(new EventArgs());//触发HttpModule自定义事件
}
protected void OnExposedEvent(EventArgs e)
{
if (ExposedEvent != null)
{
ExposedEvent(this, e);
}
}
public void Dispose()
{
}
}
Global.asax文件
1 void MyModule_ExposedEvent(object sender, EventArgs e)
2 {
3 Response.Write("xixi");
4 }
上面的MyModule_ExposedEvent方法就会自动订阅了MyModule中的ExposedEvent事件。具体实现机制有待研究!