Asp.Net高級知識回顧_HttpModule及應用程序生命周期_2
一、HttpModule事件列表
BeginRequest |
指示請求處理開始。 |
AuthenticateRequest PostAuthenticateRequest |
封裝請求身份驗證過程。 |
AuthorizeRequest PostAuthorizeRequest |
封裝請求授權過程。 |
ResolveRequestCache PostResolveRequestCache |
封裝檢查是否能利用以前緩存的輸出頁面處理請求的過程。 |
PostMapRequestHandler |
指示已發現用於處理請求的 HTTP 處理程序。 |
AcquireRequestState PostAcquireRequestState |
封裝對請求會話狀態的檢索。 |
PostRequestHandlerExecute |
指示用於處理請求的 HTTP 處理程序已執行。 |
ReleaseRequestState PostReleaseRequestState |
封裝對請求會話狀態的發布。 |
UpdateRequestCache PostUpdateRequestCache |
封裝檢查是否應對請求的資源的輸出進行緩存以備今後重復使用的過程。 |
EndRequest |
指示請求處理結束。 |
二、 HttpModule 事件流程
三、創建自定義 HTTP 模塊
我們首先看下IHttpModule接口,它包括下面兩個方法:
public void Init(HttpApplication context); public void Dispose();
Init():這個方法接受一個HttpApplication對象,HttpApplication代表當前的應用程序,我們需要在這個方法內註冊HttpApplication對象暴露給客戶端的事件。可見,這個方法僅僅是用來對事件進行註冊,而實際的事件處理程序,需要我們另外寫方法。
整個過程很好理解:
1.0 當站點第一個資源被訪問時,Asp.Net將創建HttpApplication類的實例,它代表著站點應用程序,同時會創建所有在Web.Config中註冊過的Module實例。
2.0 在創建Module實例時會調用Module的Init()方法。
3.0 在Init()方法內,對想要作出響應的HttpApplication暴露出的事件進行註冊。(僅僅進行方法的簡單註冊,實際的方法需要另寫)。
4.0 HttpApplication在其應用程序周期中觸發各類事件。
5.0 觸發事件時調用Module在其Init()方法中註冊過的方法。
Dispose():它可以在進行垃圾回收之前進行一些清理工作。
綜上所述:實現一個IHttpModule的模板一般是這樣的:
public class DefineModule:IHttpModule { public void Init(HttpApplication context) { // 註冊HttpApplication應用程序 BeginRequest 事件 // 也可以是其他任何HttpApplication暴露出的事件 context.BeginRequest += new EventHandler(context_BeginRequest); } void context_BeginRequest(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; HttpContext context = application.Context; // 做些實際的工作,HttpContext對象都獲得了,剩下的基本可以自由發揮了 } public void Dispose() { } }
四、註冊自定義 HTTP 模塊(webconfig)
1.0 IIS6及IIS7經典模式
<configuration> <system.web> <httpModules> <add name="HelloWorldModule" type="HelloWorldModule"/> </httpModules> </system.web> </configuration>
註:type=“命名空間+類別名稱,組件名稱”
2.0 為在集成模式下運行的 IIS7.0 註冊模塊
<configuration> <system.webServer> <modules> <add name="HelloWorldModule" type="HelloWorldModule"/> </modules> </system.webServer> </configuration> 註:type="命名空間+類別名稱,組件名稱"
五、HttpModule與 Global.asax 文件(新建全局應用程序類)
1.0 Global.asax文件(也稱為ASP.NET應用程序文件)是一個可選的文件,該文件包含響應ASP.NET或HTTP模塊所引發的應用程序級別和會話級別事件的代碼。Global.asax文件駐留在ASP.NET應用程序的根目錄中。運行時分析Global.asax 文件,並將其編譯到一個動態生成的 .NET Framework類,該類是從HttpApplication基類派生的。配置ASP.NET,以便自動拒絕對Global.asax文件的任何直接URL請求,外部用戶不能下載或查看其中的代碼,Global.asax文件是可選的,只在希望處理應用程序事件或會話事件時,才創建它。
Global文件的執行:
例如,IIS現在接到一個訪問ASP.NET應用程序的請求,這時候IIS會將這個請求映射給aspnet_isapi.dll,當aspnet_isapi.dll接到這個請求後,會新建一個aspnet_wp.exe的進程(windows server 2003下是w3wp.exe進程),這個進程將請求傳遞給一個被指定的AppDomain,當這個AppDomain被創建時,就會加載一些配置文件中的信息(加載順序是從machine.config文件到web.config文件中的一些相關配置),而當這些信息都被加載以後,AppDomain會去獲得一個HttpApplication的實例,這時global類就會被編譯加載了,接下來AppDomain會做一些相關的處理創建Page類的實例,最後這個頁面呈現到客戶端瀏覽器上。但這裏有一點問題需要註意,當配置文件被加載的時候,並不是表示AppDomain會加載配置文件中所有的信息,而僅是加載一些需要的信息。而有些配置信息是在需要時,才會被AppDomain加載。例如我們在web.config文件中配置了很多HttpModule,僅當每一個HttpModule被訪問到時,AppDomain才會去加載並處理這些信息。所以說web.config文件和global沒有先後執行的順序,只是視具體的信息什麽時候被加載和處理。
Global.asax.cs中的方法的含義:
Application_Init:在每一個HttpApplication實例初始化時執行。
Application_Disposed:在每一個HttpApplication實例被銷毀之前執行。
Application_Error:所有沒有處理的錯誤都會導致這個方法的執行。
Application_Start:在程序初始化時執行。在Web應用程序的生命周期裏就執行一次,這裏只能放一些公用的信息,比如HttpApplicationState。
Application_End:應用程序結束時,在最後一個HttpApplication銷毀之後執行。對應Application_Start,在整個生命周期裏面也只執行一次。
Session_Start:會話開始時執行。
Session_End:會話結束或過期時執行。
Application_BeginRequest:BeginRequest是在收到Request時第一個觸發的事件,這個方法第一個執行。
Application_AuthenticateRequest:當安全模塊已經建立了當前用戶的標識後執行。
Application_AuthorizeRequest:當安全模塊已經驗證了當前用戶的授權時執行。
Application_ResolveRequestCache:當ASP.NET完成授權事件以使緩存模塊從緩存中為請求提供服務時發生,從而跳過處理程序(頁面或者是WebService)的執行。這樣做可以改善網站的性能,這個事件還可以用來判斷正文是不是從Cache中得到。
Application_AcquireRequestState:當ASP.NET獲取當前請求所關聯的當前狀態(如Session)時執行。
Application_PreRequestHandlerExecute:當ASP.NET即將把請求發送到處理程序對象(頁面或者是WebService)之前執行,此時Session就可以使用了。
Application_PostRequestHandlerExecute:當處理程序對象工作完成後執行。
Application_ReleaseRequestState:在ASP.NET執行完所有請求處理程序後執行。ReleaseRequestState事件將使當前狀態數據被保存。
Application_UpdateRequestCache:在ASP.NET執行完處理程序後為了後續的請求而更新響應緩存時執行。
Application_EndRequest:同上,EndRequest是在響應Request時最後一個觸發的事件,此方法自然就是最後一個執行。
Application_PreSendRequestHeaders:向客戶端發送Http標頭之前執行。
Application_PreSendRequestContent:向客戶端發送Http正文之前執行。
六、 Global與HttpModule的選擇
可以在應用程序的 Global.asax 文件中實現HttpModule的許多功能,這使您可以響應應用程序事件。HttpModule相對於Global.asax文件具有如下優點:HttpModule可以進行封裝,可以在創建一次後在許多不同的應用程序中使用。如果將它們添加到全局程序集緩存(GAC)並將它們註冊到 Machine.config 文件中,便可以跨應用程序重新使用它們。
使用Global.asax文件有一個好處,那就是可以將代碼放在其他已註冊的模塊事件(如 Session_Start和Session_End方法)中。此外Global.asax 文件還允許實例化,可在整個應用程序中使用全局對象。
當需要創建依賴應用程序事件的代碼並且希望在其他應用程序中重用HttpModule時,或不希望將復雜代碼放在Global.asax文件中時,應當使用HttpModule。當需要創建依賴應用程序事件的代碼但不需要跨應用程序重用它時,或者需要訂閱不可用於HttpModule的事件(如 Session_Start)時,應當將代碼放在 Global.asax 文件中。
七、註意點:HttpModule中哪些過程中不可以使用哪些對象
在AcquireRequestState事件之前不能使用Session,因為還沒有加載Session狀態。
在MapHandlerExecutionStep事件之前不能使用緩存,因為沒有加載Handler狀態。
八、移除不必要的HttpModule可以優化性能
在.NET Framework 2.0版本的Web.config文件中配置的內置HttpModule,可以根據實際需要移除不需要的HttpModule,從而優化性能。例如,動易產品就根據實際情況移除了下面幾個HttpModule: <remove name="WindowsAuthentication" /> 啟用 Windows 身份驗證的情況下設置 ASP.NET 應用程序用戶的標識。 <remove name="PassportAuthentication" /> 提供圍繞 Passport 身份驗證服務的包裝。 <remove name=" RoleManager" /> 管理當前用戶的 RolePrincipal 實例。 <remove name="FileAuthorization" /> 驗證遠程用戶是否具有訪問所請求的文件的權限。 <remove name="AnonymousIdentification" /> 管理 ASP.NET 應用程序的匿名標識符。 <remove name="Profile" /> 管理用戶配置文件和配置文件事件的創建。
Asp.Net高級知識回顧_HttpModule及應用程序生命周期_2