httpModules是往當前應用程式添加HttpModule(http模塊)的標簽。配置節如下 提起httpModule不得不提一下Http請求處理流程 ASP.NET對請求處理的過程: 當請求一個*.aspx文件的時候,這個請求會被inetinfo.exe進程截獲,它判斷文件的尾碼(aspx)之 ...
httpModules是往當前應用程式添加HttpModule(http模塊)的標簽。配置節如下
<httpModules> <add name="ModuleName" type=".NET Class, Assembly [,Version=version number] [,Culture=culture] [,PublicKeyToken=token]"/> <remove... /> <clear/> </httpModules>
提起httpModule不得不提一下Http請求處理流程
ASP.NET對請求處理的過程:
當請求一個*.aspx文件的時候,這個請求會被inetinfo.exe進程截獲,它判斷文件的尾碼(aspx)之後,將這個請求轉交給ASPNET_ISAPI.dll,ASPNET_ISAPI.dll會通過http管道(Http PipeLine)將請求發送給ASPNET_WP.exe進程,在ASPNET_WP.exe進程中通過HttpRuntime來處理這個請求,處理完畢將結果返回客戶端。
Http 管道:
1. HttpRuntime將Http請求轉交給 HttpApplication,HttpApplication代表著程式員創建的Web應用程式。HttpApplication創建針對此Http請求的 HttpContext對象,這些對象包含了關於此請求的諸多其他對象,主要是HttpRequest、HttpResponse、HttpSessionState等。這些對象在程式中可以通過Page類或者Context類進行訪問。、
2. 接下來Http請求通過一系列Module,這些Module對Http請求具有完全的控制權。這些Module可以做一些執行某個實際工作前的事情。
3. Http請求經過所有的Module之後,它會被HttpHandler處理。在這一步,執行實際的一些操作,通常也就是.aspx頁面所完成的業務邏輯。可能你會覺得在創建.aspx頁面並沒有體會到這一過程,但是,你一定知道,.aspx 頁面繼承自Page類,我們看一下Page類的簽名:
public class Page : TemplateControl, IHttpHandler{ // 代碼省略 }
可以看到,Page類實現了IHttpHandler介面,HttpHandler也是Http請求處理的最底層。
4.HttpHandler處理完以後,Http請求再一次回到Module,此時Module可以做一些某個工作已經完成了之後的事情。
從第二步到第四步可以用下麵的圖來展示
在http請求的處理過程中,只能調用一個HttpHandler,但可以調用多個HttpModule。
下麵則詳細說說HttpModule
HTTP 模塊是一個在每次針對應用程式發出請求時調用的程式集。HTTP 模塊作為請求管道的一部分調用,它們能夠在整個請求過程中訪問生命周期事件。因此,HTTP 模塊使您可以檢查傳入的請求並根據該請求進行操作。它們還使您可以檢查傳出的響應並修改它。
ASP.NET HTTP 模塊針對所有請求調用,這與 ISAPI 篩選器類似。但是它們是用托管代碼編寫的,而且可以與 ASP.NET 應用程式的生命周期完全集成。可以將自定義模塊源代碼放在應用程式的 App_Code 文件夾中,也可以將經過編譯的自定義模塊作為程式集放在應用程式的 Bin 文件夾中。
ASP.NET 使用模塊來實現各個應用程式功能,其中包括 Forms 身份驗證、緩存、會話狀態和客戶端腳本服務。在每種情況下,如果這些服務處於啟用狀態,模塊會作為請求的一部分調用,並執行在任何單一頁請求範圍之外的任務。模塊可以使用應用程式事件,可能會引發可在 Global.asax 文件中處理的事件。
功能:
模塊可以訂閱多種請求管道通知。模塊可以接收 HttpApplication 對象的事件通知。
使用場景
HTTP 模塊通常具有以下用途:
- 安全 因為您可以檢查傳入的請求,所以 HTTP 模塊可以在調用請求頁、XML Web services 或處理程式之前執行自定義的身份驗證或其他安全檢查。在以集成模式運行的 Internet 信息服務 (IIS) 7.0 中,可以將 Forms 身份驗證擴展到應用程式中的所有內容類型。
- 統計信息和日誌記錄 因為 HTTP 模塊是在每次請求時調用的,所以,您可以將請求統計信息和日誌信息收集到一個集中的模塊中,而不是收集到各頁中。
- 自定義的頁眉或頁腳 因為您可以修改傳出響應,所以可以在每一個頁面或 XML Web services 響應中插入內容,如自定義的標頭信息。
ASP.NET中一些內置的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 |
捕捉異常,格式化錯誤提示字元,傳遞給客戶端程式 |
下麵摘抄了MSDN上的一個例子,自定義一個HttpModule
HttpModule必須實現介面System.Web.IHttpModule
namespace FastDoge.Study { public class MyModule : IHttpModule { public void Dispose() { } public void Init(HttpApplication context) { context.BeginRequest += (new EventHandler(this.Application_BeginRequest)); context.EndRequest += (new EventHandler(this.Application_EndRequest)); } private void Application_BeginRequest(Object source, EventArgs e) { HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; context.Response.Write("<h1><font color=red>" + "HelloWorldModule: Beginning of Request" + "</font></h1><hr>"); } private void Application_EndRequest(Object source, EventArgs e) { HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; context.Response.Write("<hr><h1><font color=red>" + "HelloWorldModule: End of Request</font></h1>"); } }
在 IIS 6.0 和 IIS 7.0 經典模式下運行的Web.config添加以下配置
<configuration> <system.web> <httpModules> <add name="myModule" type="FastDoge.Study.MyModule"/> </httpModules> </system.web> </configuration>
由於鄙人用的是IIS7集成模式,配置會不一樣
<system.webServer> <modules> <add name="myModule" type="FastDoge.Study.MyModule"/> </modules> </system.webServer>
效果如下所示
當然網站不能是空網站,否則輸出的只是一行
<hr><h1><font color=red>HelloWorldModule: End of Request</font></h1>
的字元串。在Init方法中傳入的HttpApplication 對象可以綁定的事件可以參考ASP.NET 應用程式生命周期中提到的,事件一共20幾個。
在網上找了一幅圖,列出了事件觸發的順序
BeginRequest和PreRequestHandlerExecute之間的事件是在伺服器執行HttpHandler處理之前觸發。
PostRequestHandlerExecute和PreSendRequestContent之間的事件是在伺服器執行Handler處理之後觸發。
可是鄙人糾結的一點在於沒發現某個ASP.NET內置的HttpModule調用了Handler。對於ASP.NET WebForm來說,每個Page都是一個Handler。而對ASP.NET MVC來說,在之前看蔣金楠老是的著作時看到的是觸發一個UrlRoutingModule,它在OnPostResolveRequestCache事件中給HttpContext指定了一個MvcHandler。這樣就會使得HttpHandler會被調用?或許需要看一下源碼了。另外還有一個值得學習的地方就是這種模塊的添加以及往Application註冊事件的形式,使得HttpApplication具備的較好的靈活性。
在入行之初寫過一篇博客,就用到HttpModule,當時有位園友評論說可以用Global.asax。結合當時的場景確實如此。但是兩者對比起來肯定有弊有利。
模塊相對於 Global.asax 文件具有如下優點:模塊可以進行封裝,因此可以在創建一次後在許多不同的應用程式中使用。
用 Global.asax 文件的好處在於可以處理其他已註冊事件,如 Session_Start 和 Session_End。此外,Global.asax 文件還允許您實例化可在整個應用程式中使用的全局對象。
當您必須創建依賴應用程式事件的代碼,並且符合以下條件時,都應該使用模塊:
- 希望在其他應用程式中重用該模塊。
- 希望避免將複雜代碼放在 Global.asax 文件中。
- 該模塊應用於管道中的所有請求(僅限 IIS 7.0 集成模式)。
當您必須創建依賴應用程式事件的代碼並且不需要跨應用程式重用代碼時,應該將代碼添加到 Global.asax 文件中。