HttpModule & HttpHandler

ASP.NET 處理請求的過程

  • inetinfo.exe:www 服務進程,IIS 服務 和 ASPNET_ISAPI.dll 都寄存在此進程中。
  • ASPNET_ISAPI.dll:處理 .aspx 文件的 win32 組件。其實,IIS 服務器只能識別 .html 文件的,當發現被請求的文件是 .aspx 文件時,IIS 服務器將其交給 aspnet_isapi.dll 來處理。
  • aspnet_wp.exe 進程:ASP.NET 框架進程,提供 .net 運行的託管環境,CLR (公共語言運行時)就是寄存在此進程中。

ASP.NET Framework 處理一個 Http Request 的流程:html

HttpRequest → inetinfo.exe → ASPNET_ISAPI.dll → ASPNET_WP.exe → HttpRuntime → HttpApplication Factory → HttpApplication → HttpModule → HttpHandler Factory → HttpHandler → HttpHandler.ProcessRequest()web

       ASP.NET 請求處理過程是基於管道模型的,ASP.NET 把 http 請求依次傳遞給管道中各個 HttpModule,最終被 HttpHandler 處理,處理完成後,再次通過管道中的 HttpModule,把結果返回給客戶端。注意:在 http 請求的處理過程當中,只能調用一個 HttpHandler,但能夠調用多個 HttpModule。api

       在每一個 HttpModule 中均可以干預請求的處理過程。當請求到達 HttpModule 的時候,系統尚未對這個請求真正處理,可是咱們能夠在這個請求傳遞處處理中心(HttpHandler)以前附加一些其它信息,截獲這個請求並做一些額外的工做,或者終止請求等。在 HttpHandler 處理完請求以後,咱們也能夠再在相應的 HttpModule 中把請求處理的結果進行再次加工後返回客戶端。緩存

 

HttpModule

       HttpModule 是實現了 System.Web.IhttpModule 接口的類。IHttpModule 接口的聲明:服務器

public interface IHttpModule
{
    // 給予 HTTP 模塊在對象被垃圾收集以前執行清理的機會,通常無需編寫代碼。
    void Dispose();
 
    // 初始化時自動調用,可在這裏向 HttpApplication 對象中的事件註冊本身的事件處理程序
    void Init(HttpApplication context);
}

 

       HttpModule 能夠向 System.Web.HttpApplication 對象註冊下面一系列事件(事件觸發順序已排序):cookie

  1. application_BeginRequest:當 ASP.NET 運行時接收到新的 HTTP 請求時觸發。
  2. application_AuthenticateRequest:當 ASP.NET 運行時準備驗證用戶身份時觸發。
  3. application_AuthorizeRequest:當 ASP.NET 運行時準備受權用戶訪問資源的時候觸發。
  4. application_ResolveRequestCache:咱們引起這個事件來決定是否可使用從輸出緩存返回的內容來結束請求。但這依賴於 Web 應用程序的輸出緩存是怎樣設置的
  5. application_AcquireRequestState:當 ASP.NET 運行時準備好接收當前 HTTP 請求的會話狀態的時候引起這個事件。
  6. application_PreRequestHandlerExecute:在 ASP.NET 開始執行 HTTP 請求的處理程序以前引起這個事件。在這個事件以後,ASP.NET 把該請求轉發給適當的HTTP處理程序。
  7. application_PostRequestHandlerExecute:在 HTTP 處理程序結束執行的時候引起這個事件。
  8. application_ReleaseRequestState:當 ASP.NET 結束全部的請求處理程序執行的時候引起這個事件。
  9. application_EndRequest:把響應內容發送到客戶端以前引起這個事件。
  10. application_PreSendRequestHeaders:在 ASP.NET 把 HTTP 響應頭信息發送給客戶端以前引起這個事件。在頭信息到達客戶端以前,這個事件容許咱們改變它的內容。咱們可使用這個事件在頭信息中添加cookie 和自定義數據
  11. application_PreSendRequestContent:在 ASP.NET 把響應內容發送到客戶端以前引起這個事件。這個事件容許咱們在內容到達客戶端以前改變響應內容。咱們可使用這個事件給頁面輸出添加用於全部頁面的內容。例如通用菜單、頭信息、腳信息或某些註釋與標記

       其他,還有 Error 事件(在處理 HTTP 請求的過程當中出現未處理的異常時觸發),Deposed 事件(當 ASP.NET 完成 HTTP 請求的處理過程時觸發),UpdateRequestCache 事件(當 ASP.NET 完成了當前的 HTTP 請求的處理,而且輸出內容已經準備好添加給輸出緩存時觸發。這依賴於 Web 應用程序的輸出緩存是如何設置的)。app

       HttpModule & HttpHandler 的生命週期圖:框架

       2010111515341046

 

HttpModule 使用示例1

       有的網站每個頁面都會彈出一個廣告或在每一個頁面都以註釋形式(<!-- -->)加入網站的版權信息。若是在每一個頁面教編寫這樣的 JS 代碼,編寫會很繁瑣,更改和維護將很是困難。
       HttpModule 是客戶端發出請求到客戶端接收到服務器響應之間的一段必經之路。咱們徹底能夠在服務器處理完請求以後,並在向客戶端發送響應文本以前這段時機,把這段註釋文字添加到頁面文本以後。這樣,每個頁面請求都會被附加上這段註釋文字。那麼,這段代碼究竟該在哪一個事件裏實現呢? PostRequestHandlerExecute 和 PreSendRequestContent 之間的任何一個事件均可以,但通常會在 EndRequest 事件裏編寫代碼,具體實現步驟以下:
網站

  1. 添加自定義的管道類,並實現 IHttpModule 接口
  2. 在 Init 事件中註冊 EndRequest 事件,實現事件處理方法
  3. 在 Web.Conofig 中註冊自定義 HttpModule
public class TestModule : IHttpModule
{
    public void Dispose()
    {
       
    }
 
    public void Init(HttpApplication context)
    {
        context.EndRequest +=  context_EndRequest;
    }
 
    void context_EndRequest(object sender, EventArgs e)
    {
        ((HttpApplication)sender).Response.Write("<!-- 公司版權 -->");
    }
}
<httpModules>
  <add name="TestModule" type="ASP.NET_Web_Form.Util.TestModule,ASP.NET_Web_Form.Util"/>
</httpModules>

 

HttpModule 使用示例2

       在做登陸時,登陸成功後,通常要把用戶名放在 Session 中保存,在其它每個頁面的 Page_Load 事件中都檢查 Session 中是否存在用戶名,若是不存在就說明用戶未登陸,就不讓其訪問其中的內容。但這種作法實在是太笨拙,幾乎要在每個頁面中都加入檢測 Session 的代碼,致使難以開發和維護。下面咱們看看如何使用 HttpModule 來減小咱們的工做量。(若是每一個頁面都有共同的父類,例如 BasePage,那麼在父類的 Load 事件中檢測也是同樣的只需寫一次檢測代碼
       因爲這裏要用到 Session 中的內容,咱們只能在 AcquireRequestState 和 PreRequestHandlerExecute 事件中編寫代碼,由於在 HttpModule 中只有這兩事件中能夠訪問 Session。這裏能夠選擇PreRequestHandlerExecute 事件編寫代碼,具體實現比較簡單,就不貼代碼了。
ui

 

HttpHandler

       HttpHandler 是 HTTP 請求的處理中心,真正地對客戶端請求的服務器頁面作出編譯和執行,並將處理事後的信息附加在 HTTP 請求信息流中再次返回到 HttpModule 中。與 HttpModule 不一樣,一旦定義了本身的HttpHandler 類,那麼它對系統的 HttpHandler 的關係將是「覆蓋」

       在 web.config 中配置 HttpHandler 節時,你能夠指定 HTTP 的動詞(GET,POST),指定要處理的資源是什麼,以及用什麼 HttpHandler 來進行。

       另外,若是要在 HttpHandler 中使用 Session,那必須把該 HttpHandler 實現 IRequiresSessionState 接口,IRequiresSessionState 接口是個空接口,它沒有抽象方法,只是一個標記接口。

 

本文參考文獻:http://www.cnblogs.com/yuanyuan/archive/2010/11/15/1877709.html

相關文章
相關標籤/搜索