天天看點

IHttpModule 接口

名稱 說明
Dispose Disposes of the resources (other than memory) used by the module that implements IHttpModule.
Init Initializes a module and prepares it to handle requests.

IHttpModule接口隻有兩個方法。

void Init(HttpApplication app);

void Dispose();

Init方法接受一個服務該請求的HttpApplication對象的引用。使用該引用可以連接配接到系統事件。HttpApplication對象也有一個稱為Context的對象,該對象提供對ASP.NET應用程式的内在屬性的引用。這樣,我們就可以通路Response, Request, Session等。

表2.5列出了HTTP子產品監聽和處理的事件。

表2.5  HttpApplication事件

事  件 描    述

AcquireRequestState,

PostAcquireRequestState

當實際服務請求的處理程式獲得與該請求關聯的狀态資訊時發生。ASP.NET 1.x不支援PostAcquireRequestState事件

AuthenticateRequest,

PostAuthenticateRequest

當一個安全子產品已經建立使用者的身份時發生。ASP.NET 1.x不支援PostAuthenticateRequest事件

AuthorizeRequest,

PostAuthorizeRequest

當一個安全子產品已經驗證使用者授權時發生。ASP.NET 1.x不支援PostAuthorizeRequest事件
BeginRequest HTTP管道一開始處理請求就發出該事件
Disposed 由于調用了Dispose,HttpApplication對象被處置時發出該事件。
EndRequest 作為HTTP管道執行鍊的最後一個事件發出
Error 抛出一個未處理的異常時發生
PostMapRequestHandler 當服務請求的HTTP處理程式被找到時發出。ASP.NET 1.x不支援該事件
PostRequestHandlerExecute 當所選的HTTP處理程式完成執行時發出該事件。這時已經生成響應文本
PreRequestHandlerExecute 正好在所選的HTTP處理程式開始工作前發出該事件
PreSendRequestContent 正好在ASP.NET運作庫把響應文本發送給客戶之前發出該事件
PreSendRequestHeaders 正好在ASP.NET運作庫把HTTP頭發送給客戶之前發出該事件

ReleaseRequestState,

PostReleaseRequestState

當處理程式釋放與目前請求關聯的狀态資訊時發生。ASP.NET 1.x不支援PostReleaseRequestState事件

ResolveRequestCache,

PostResolveRequestCache

當ASP.NET運作庫通過輸出緩存解決該請求時發生。ASP.NET 1.x不支援PostResolveRequestCache事件

UpdateRequestCache,

PostUpdateRequestCache

當ASP.NET運作庫将目前請求的響應存儲在輸出緩存(用來服務随後的請求)中時發生。ASP.NET 1.x不支援PostUpdateRequestCache事件

所有這些事件由HttpApplication對象提供的,而HTTP子產品作為Init方法的一個參數接受該對象。

下面來實作這個接口:

public class MarkerModule : IHttpModule

{

    public void Init(HttpApplication app)

    {

      // Register for pipeline events

    }

    public void Dispose()

    {

      // Nothing to do here

    }

}

HttpApplication類調用Init方法來裝載該子產品。在Init方法中,通常隻需注冊自己的事件處理程式。Dispose方法多半是空的。HTTP子產品的核心實際上就是自定義的事件處理程式。

1. 綁定事件

Marker示例子產品注冊兩個管道事件,它們是BeginRequest和EndRequest。BeginRequest是開始處理請求時第一個命中HTTP應用程式對象的事件;EndRequest是表明即将處理完請求,這是實施幹預的最後機會的事件。通過處理這兩個事件,可以在正常的HTTP處理程式(派生于Page的類)之前和之後,将自定義的文本寫入輸出流中。

如下清單展示了示例子產品的Init和Dispose方法的過程實作:

public void Init(HttpApplication app)

{

    // Register for pipeline events

    app.BeginRequest += new EventHandler(OnBeginRequest);

    app.EndRequest += new EventHandler(OnEndRequest);

}

public void Dispose()

{

}

BeginRequest和EndRequest事件處理程式結構類似。它們從發送方獲得對目前HttpApplication對象的引用,并從該引用那裡獲得HTTP上下文。接着,它們使用Reponse對象追加文本或自定義标題。

public void OnBeginRequest(object sender, EventArgs e)

{

    HttpApplication app = (HttpApplication) sender;

    HttpContext ctx = app.Context;

    // More code here

    // PageHeaderText is a constant string defined elsewhere

    ctx.Response.AppendHeader("Author", "DinoE");

    ctx.Response.Write(PageHeaderText);

}

public void OnEndRequest(object sender, EventArgs e)

{

    // Get access to the HTTP context

    HttpApplication app = (HttpApplication) sender;

    HttpContext ctx = app.Context;

    // More code here

    // Append some custom text

    // PageFooterText is a constant string defined elsewhere

    ctx.Response.Write(PageFooterText);

}

OnBeginRequest寫入标準的頁面标題文本并添加一個自定義的HTTP頭。OnEndRequest隻是追加頁面的頁腳。該HTTP子產品的效果如圖2.7所示。

圖2.7  Marker HTTP子產品将一個标題和頁腳添加到應用程式内的每個頁面

 注意    圖中的工具,即IEWatch 2.0,是Microsoft Internet Explorer的一個插件程式,該工具可以分析HTTP/HTTPS請求和HTML源代碼。我們可以從http://www.iewatch.com擷取它。

Internet Explorer底部的可停靠視窗,展示了浏覽器正在發送和接收的所有HTTP頭。顯然,響應文本中的自定義的标題是可見的。

2. 用配置檔案注冊該子產品

通過向配置檔案的<httpModules>節添加一個配置項,可以注冊一個新的HTTP子產品。<httpModules>配置節的文法類似于HTTP處理程式的文法。使用<add>節點,并規定name和type屬性可以添加一個新的子產品。name屬性包含該子產品的公開名稱。該名稱将被用來選擇HttpApplication的Modules集合中的子產品。如果該子產品激發自定義事件,則該名稱還可以在global.asax檔案中用作建構自動的事件處理程式的字首。

<system.web>

<httpModules>

<add name="Marker"

type="ProAspNet20.CS.Components.MarkerModule,ProAspCompLib" />

</httpModules>

</system.web>

type屬性使用常見的逗号隔離字元串,它可設定類及其相關程式集的名稱。這些配置設定既可以存儲在應用程式配置檔案中,也可以存儲在機器配置檔案中。在前一種情況中,隻有應用程式的頁面受影響;而在後一種情況下,所有應用程式中的所有頁面都将由指定的子產品進行處理。

這些子產品的應用順序取決于其在配置清單中的實體順序。可以删掉一個系統子產品,并用我們自己的具有類似功能的子產品替換它。在這種情況下,在應用程式的web.config檔案中,使用<remove>節點删去預設子產品,然後使用<add>插入自己的子產品。如果需要完全重新定義HTTP子產品的應用順序,可以使用<clear>節點清除所有的預設子產品,然後按自己喜歡的順序重新注冊它們。

3. 通路其他HTTP子產品

剛剛讨論的示例說明了如何綁定管道事件——即,HttpApplication對象激發的事件。但是其他子產品激發的事件是什麼呢?HttpApplication對象提供了一個名為Modules的屬性,它獲得目前應用程式子產品的集合。

Modules屬性的類型為HttpModuleCollection,其中包括應用程式子產品的名稱。該集合類繼承自NameObjectCollectionBase抽象類,這是一個由字元串和對象組成的組合對的集合。字元串訓示子產品的公開名稱,對象是該子產品的真實執行個體。要通路處理會話狀态的子產品,需要如下編碼:

SessionStateModule sess = app.Modules["Session"];

sess.Start += new EventHandler(OnSessionStart);

如前所述,還可以在global.asax檔案中處理HTTP子產品引起的事件,并使用ModuleName_EventName規則來命名事件處理程式。子產品名稱隻是在注冊一個HTTP子產品時需要定義的設定之一。