前言
繼上一篇理解並自定義HttpHandler后,有進行了HttpModule的進一步學習,本篇作為一個小結。
主要參考:Asp.Net 構架(HttpModule 介紹) - Part.3
目錄
Asp.net的事件分為三級:應用程序級、頁面級和控件級。而HttpModule是通過在管道模型中對Asp.net的應用程序級事件進行訂閱,當應用程序級事件觸發時調用HttpModule中對應的處理方法。也就是說HttpModule是訂閱Asp.net應用程序級事件的入口,依附於HttpApplication對象生命周期的各個事件。
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跟自定義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都繼承System.Web.IHttpModule接口,並實現接口的Init(HttpApplication context)和Dispose()方法。如下:
1 public class MyModule:IHttpModule
2 {
3
4 public void Init(HttpApplication context)
5 {
6 context.BeginRequest += new EventHandler(context_BeginRequest);
7 }
8
9 void context_BeginRequest(object sender, EventArgs e)
10 {
11 HttpContext.Current.Response.Write("BeginRequest");
12 }
13
14 public void Dispose()
15 {
16 }
17 }
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文件
1 public class MyModule:IHttpModule
2 {
3 public event EventHandler ExposedEvent;//HttpModule事件,供Global.asax來訂閱
4
5 public void Init(HttpApplication context)
6 {
7 context.BeginRequest += new EventHandler(context_BeginRequest);//訂閱HttpApplication的事件
8 }
9
10 void context_BeginRequest(object sender, EventArgs e)
11 {
12 HttpContext.Current.Response.Write("BeginRequest");
13 OnExposedEvent(new EventArgs());//觸發HttpModule自定義事件
14 }
15
16 protected void OnExposedEvent(EventArgs e)
17 {
18 if (ExposedEvent != null)
19 {
20 ExposedEvent(this, e);
21 }
22 }
23
24 public void Dispose()
25 {
26 }
27 }
Global.asax文件
1 void MyModule_ExposedEvent(object sender, EventArgs e)
2 {
3 Response.Write("xixi");
4 }
上面的MyModule_ExposedEvent方法就會自動訂閱了MyModule中的ExposedEvent事件。具體實現機制有待研究!