Author:uestc95 ArticleType:原創 E-mail:uestc95@263.net .NET Framework Version:1.0.3705正式版 VS.NET(C#) Version:7.0.9466正式版 這幾天胃口還算好,雖然算不上“吃嘛嘛香”,但是也算是不錯了,但願能增上幾斤才好。 怎麼樣,我們在Chapter Two最後提出的兩個問題估計早出來了吧,:) First:為什麼在HttpModule中不能使用Session? Second:系統預設的幾個HttpModule在哪裡配置的? 我們先挑軟柿子捏,第二個問題的答案是:在檔案machine.config中配置,比如在你的系統檔案目錄中的C:WI NNTMicrosoft.NETFrameworkv1.0.3705CONFIGmachine.config。 雖然是個軟柿子,但是還是有些東東在裡面的,那就是machine.config和我們常見的web.config有什麼關 系呢?在ASP.NET Framework啟動處理一個Http Request的時候,她會依次載入machine.config以及你請求頁面 所在目錄的web.config檔案,裡面的配置是有<remove>標籤的,什麼意思不說也知道了吧。如果你在machine.c onfig中配置了一個自己的HttpModule,你仍然可以在離你最近web.config檔案中“remove”掉這個映射關係。 至於第一個問題,呵呵,如果你仔細的運行過上次的檔案但是沒有自己仔細深入研究一下的話,一定會覺 得在HttpModule中的確無法使用Session,:)。如果你發現上次提出的問題本身就是一個"Problem",那麼恭喜你,你沒有掉進我故意給出的框框中,並且很有質疑精神,:) 今天我們就來解釋一下HttpModule和HttpHandler之間的關係,在今天的“日記”完成的時候,你也就會發現第一個問題的答案了。 Chapter Three -- 深入HttpModule 我們曾經提及當一個Http Request被ASP.NET Framework捕獲之後會依次交給HttpModule以及HttpHandler來處理,但是不能理解為HttpModule和HttpHandler是完全獨立的,實際上是,在Http Request在HttpModule傳遞的過程中會在某個事件內將控制權交給HttpHandler的,而真正的處理在HttpHandler中完成之後,再將控制權交還給HttpModule。也就是說HttpModule在某個請求經過她的時候會再恰當時候同HttpHandler進行通訊,在何時,如何通訊呢?這就是下面提到的了。 我們提到在HttpModule中最開始的事件是BeginRequest,最終的事件是EndRequest。你如果仔細看上次給出的來源程式的話,應當發現在方法Init()中參數我們傳遞的是一個HttpApplication類型,而我們曾經提及的兩個事件正是這個傳遞進來的HttpApplication的事件之一。 HttpApplication還有其它的事件,分別如下: application.BeginRequest application.EndRequest application.PreRequestHandlerExecute application.PostRequestHandlerExecute application.ReleaseRequestState application.AcquireRequestState application.AuthenticateRequest application.AuthorizeRequest application.ResolveRequestCache application.PreSendRequestHeaders application.PreSendRequestContent 需要注意的是,在事件EndRequest之後還會繼續執行application.PreSendRequestHeaders以及application.PreSendRequestContent事件,而這兩個事件大家想必應當從名稱上面看得出來事做什麼用途的了吧。是的,一旦觸發了這兩個事件,就表明整個Http Request的處理已經完成了,在這兩個事件中是開始向用戶端傳送處理完成的資料流了。看到這裡,您應當有一個疑問才對:怎麼沒見到HttpHandler就處理完成了?不是提到過HttpHandler才是真正處理Http Request的嗎?如果你有這個疑問表明你是仔細在看,也不枉我打字打得這莫累,:)。 其實一開始我就提到了,在一個http request在HttpModule傳遞過程中,會在某一個時刻(確切的說應當是事件)中將這個請求傳遞給HttpHandler的。這個事件就是ResolveRequestCache,在這個事件之後,HttpModule會建立一個HttpHandler的入口執行個體(做好準備了,:)),但是此時並沒有將控制權交出,而是繼續觸發AcquireRequestState以及PreRequestHandlerExecute事件(如果你實現了的話)。看到了嗎,最後一個事件的首碼是Pre,呵呵。這表明下一步就要進入HttpHandler了,的確如此,正如我們猜想的那樣,在PreRequestHandlerExecute事件之後,HttpModule就會將控制權暫時交給HttpHandler,以便進行真正的http request處理工作。而在HttpHandler內部會執行ProcessRequest來處理請求。在HttpHandler處理完畢之後,會將控制權交還給HttpModule,HttpModule便會繼續對處理完畢的http Request進行層層的轉交動作,直到返回到用戶端。 怎麼樣,是不是有些混亂?呵呵,苦於純文字無法畫流程圖,我手頭上已經畫好了一個整個HttpModule的生命週期圖,我只能暫且在這裡用字元描繪一下前後流程了,如果你想要這個圖片,可以給我發送mail,我給你mail過去。 Http Request在整個HttpModule中的生命週期圖: Http Request開始 | HttpModule | HttpModule.BeginRequest() | HttpModule.AuthenticateRequest() | HttpModule.AuthorizeRequest() | HttpModule.ResolveRequestCache() | 建立HttpHandler控制點 | 接著處理(HttpHandler已經建立,此後Session可用) | HttpModule.AcquireRequestState() | HttpModule.PreRequestHandlerExecute() | 進入HttpHandler處理HttpRequest | HttpHandler.ProcessRequest() | 返回到HttpModule接著處理(HttpHandler生命週期結束,Session失效) | HttpModule.PostRequestHandlerExecute() | HttpModule.ReleaseRequestState() | HttpModule.UpdateRequestCache() | HttpModule.EndRequest() | HttpModule.PreSendRequestHeaders() | HttpModule.PreSendRequestContent() | 將處理後的資料返回用戶端 | 整個Http Request處理結束 怎麼樣,從上面的圖中應當找到上次我們提出的第一個問題的答案了吧。 為了驗證上面的流程,我們可以用下面的這個自己的HttpModuel來驗證一下就知道了。 注意我們下面給出的是類的內容,架構還是前次我們給出的那個,自己加上就好了: public void Init(HttpApplication application) { application.BeginRequest += (new EventHandler(this.Application_BeginRequest)); application.EndRequest += (new EventHandler(this.Application_EndRequest)); application.PreRequestHandlerExecute +=(new EventHandler(this.Application_PreRequestHandlerExecute)); application.PostRequestHandlerExecute +=(new EventHandler(this.Application_PostRequestHandlerExecute)); application.ReleaseRequestState +=(new EventHandler(this.Application_ReleaseRequestState)); application.AcquireRequestState +=(new EventHandler(this.Application_AcquireRequestState)); application.AuthenticateRequest +=(new EventHandler(this.Application_AuthenticateRequest)); application.AuthorizeRequest +=(new EventHandler(this.Application_AuthorizeRequest)); application.ResolveRequestCache +=(new EventHandler(this.Application_ResolveRequestCache)); application.PreSendRequestHeaders +=(new EventHandler(this.Application_PreSendRequestHeaders)); application.PreSendRequestContent +=(new EventHandler(this.Application_PreSendRequestContent)); } private void Application_PreRequestHandlerExecute(Object source, EventArgs e) { HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; context.Response.Write("Application_PreRequestHandlerExecute<br>"); } private void Application_BeginRequest(Object source, EventArgs e) { HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; context.Response.Write("Application_BeginRequest<br>"); } private void Application_EndRequest(Object source, EventArgs e) { HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; context.Response.Write("Application_EndRequest<br>"); } private void Application_PostRequestHandlerExecute(Object source,EventArgs e) { HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; context.Response.Write("Application_PostRequestHandlerExecute<br>"); } private void Application_ReleaseRequestState(Object source, EventArgs e) { HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; context.Response.Write("Application_ReleaseRequestState<br>"); } private void Application_UpdateRequestCache(Object source, EventArgs e) { HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; context.Response.Write("Application_UpdateRequestCache<br>"); } private void Application_AuthenticateRequest(Object source, EventArgs e) { HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; context.Response.Write("Application_AuthenticateRequest<br>"); } private void Application_AuthorizeRequest(Object source, EventArgs e) { HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; context.Response.Write("Application_AuthorizeRequest<br>"); } private void Application_ResolveRequestCache(Object source, EventArgs e) { HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; context.Response.Write("Application_ResolveRequestCache<br>"); } private void Application_AcquireRequestState(Object source, EventArgs e) { HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; context.Response.Write("Application_AcquireRequestState<br>"); } private void Application_PreSendRequestHeaders(Object source, EventArgs e) { HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; context.Response.Write("Application_PreSendRequestHeaders<br>"); } private void Application_PreSendRequestContent(Object source, EventArgs e) { HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; context.Response.Write("Application_PreSendRequestContent<br>"); } public void Dispose() { } 好了,手累的不行了,:) 老規矩,下面的問題仔細考慮: HttpModule中的Application的多個事件和Global.asax中的Application事件有聯絡嗎?如果有,該會有哪些聯絡呢? 下回會探討HttpHandler的構建了,:) 不過最近挺忙,不知道何時能繼續......儘力吧。 See you later. |