名稱 | 說明 |
---|---|
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子產品時需要定義的設定之一。