HttpContext, HttpModules 和 HttpHandlers

  httpApplication它本身對發送給應用程序的數據一無所知-它只是一個通過事件來通訊的消息對象.它觸發事件並通過HttpContext對象來向被調用函數傳遞消息.實際的當前請求的狀態數據由前面提到的HttpContext對象維護.它提供了所有請求專有的數據並從進入管道開始到結束一直跟隨請求.圖7顯示了ASP.NET管道中的流程.注意上下文對象(即HttpContext),這個從請求開始到結束一直都是你”朋友”的對象,可以在一個事件處理函數中保存信息並在以後的事件處理函數中取出.
  
    一旦管道被啓動,HttpApplication開始象圖六那樣一個個的觸發事件.每個事件處理器被觸發,如果事件被掛接,這些處理器將執行它們自己的任務.這個處理的主要任務是最終調用掛接到此特定請求的HttpHandler.處理器(handler)是ASP.NET請求的核心處理機制,通常也是所有應用程序級別的代碼被執行的地方.記住ASP.NET頁面和Web服務框架都是作爲HttpHandler實現,這裏也是處理請求的的核心之處.模塊(module)趨向於成爲一個傳遞給處理器(handler)的上下文的預處理或後處理器.ASP.NET中典型的默認處理器包括預處理的認證,緩存以及後處理中各種不同的編碼機制.
  
    有很多關於HttpHandler和HttpModule的可用信息,所以爲了保持這篇文章在一個合理的長度,我將提供一個關於處理器的概要介紹.

HttpModule
  
    當請求在管道中傳遞時,HttpApplicaion對象中一系列的事件被觸發.我們已經看到這些事件在Global.asax中作爲事件被髮布.這種方法是特定於應用程序的,可能並不總是你想要的.如果你要建立一個通用的可用被插入任何Web應用程序的HttpApplication事件鉤子,你可用使用HttpModule,這是可複用的,不需要特定語應用程序代碼的,只需要web.config中的一個條目.
  
    模塊本質上是過濾器(fliter)-功能上類似於ISAPI過濾器,但是它工作在ASP.NET請求級別上.模塊允許爲每個通過HttpApplication對象的請求掛接事件.這些模塊作爲外部程序集中的類存貯.,在web.config文件中被配置,在應用程序啓動時被載入.通過實現特定的接口和方法,模塊被掛接到HttpApplication事件鏈上.多個HttpModule可用被掛接在相同的事件上,事件處理的順序取決於它們在Web.config中聲明的順序.下面是在Web.config中處理器定義.
  
  <configuration>
  <system.web>
  <httpModules>
  <add name= "BasicAuthModule"
  type="HttpHandlers.BasicAuth,WebStore" />
  </httpModules>
  </system.web>
  </configuration>
  
    注意你需要指定完整的類型名和不帶dll擴展名的程序集名.
  
    模塊允許你查看每個收到的Web請求並基於被觸發的事件執行一個動作.模塊在修改請求和響應數據方面做的非常優秀,可用爲特定的程序提供自定義認證或者爲發生在ASP.NET中的每個請求增加其他預處理/後處理功能.許多ASP.NET的功能,像認證和會話(Session)引擎都是作爲HttpModule來實現的.
  
    雖然HttpModule看上去很像ISAPI過濾器,它們都檢查每個通過ASP.NET應用的請求,但是它們只檢查映射到單個特定的ASP.NET應用或虛擬目錄的請求,也就是隻能檢查映射到ASP.NET的請求.這樣你可以檢查所有ASPX頁面或者其他任何映射到ASP.NET的擴展名.你不能檢查標準的.HTM或者圖片文件,除非你顯式的映射這些擴展名到ASP.NET ISAPI dll上,就像圖1中展示的那樣.一個常見的此類應用可能是使用模塊來過濾特定目錄中的JPG圖像內容並在最上層通過GDI+來繪製’樣品’字樣.
  
    實現一個HTTP模塊是非常簡單的:你必須實現之包含兩個函數(Init()和Dispose())的IHttpModule接口.傳進來的事件參數中包含指向HTTPApplication對象的引用,這給了你訪問HttpContext對象的能力.在這些方法上你可以掛接到HttpApplication事件上.例如,如果你想掛接AuthenticateRequest事件到一個模塊上,你只需像列表5中展示的那樣做
  
    列表5:基礎的HTTP模塊是非常容易實現的
  
  public class BasicAuthCustomModule : IHttpModule
  {
   public void Init(HttpApplication application)
   {
    // *** Hook up any HttpApplication events
    application.AuthenticateRequest += new EventHandler(this.OnAuthenticateRequest);
   }
   public void Dispose() { }
  
   public void OnAuthenticateRequest(object source, EventArgs eventArgs)
   {
    HttpApplication app = (HttpApplication) source;
    HttpContext Context = HttpContext.Current;
    … do what you have to do… }
   }
  
    記住你的模塊訪問了HttpContext對象,從這裏可以訪問到其他ASP.NET管道中固有的對象,如請求(Request)和響應(Response),這樣你還可以接收用戶輸入的信息等等.但是記住有些東西可能是不能訪問的,它們只有在處理鏈的後段才能被訪問.
  
    你可以在Init()方法中掛接多個事件,這樣你可以在一個模塊中實現多個不同的功能.然而,將不同的邏輯分到單獨的類中可能會更清楚的將模塊進行模塊化(譯註:這裏的模塊化和前面的模塊沒有什麼關係)在很多情況下你實現的功能可能需要你掛接多個事件-例如一個日誌過濾器可能在BeginRequest事件中記錄請求開始時間,然後在EndRequest事件中將請求結束寫入到日誌中.
  
    注意一個HttoModule和HttpApplication事件中的重點:Response.End()或HttpApplication.CompleteRequest()會在HttpApplication和Module的事件鏈中”抄近道”.看”注意Response.End()”來獲得更多信息.
  
    注意Response.End()
  
    當創建HttpModule或者在Global.asax中實現事件鉤子的時候,當你調用Response.End或 Appplication.CompleteRequest的時候要特別注意.這兩個函數都結束當前請求並停止觸發在HTTP管道中後續的事件,然後發生將控制返回到Web服務器中.當你在處理鏈的後面有諸如記錄日誌或對內容進行操作的行爲時,因爲他們沒有被觸發,有可能使你上當.例如,sample中logging的例子就會失敗,因爲如果調用Response.End()的話,EndRequest事件並不會被觸發

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章