最近學習WCF知識時看到有關IIS版本的知識,發現對HttpContext,HttpModule,HttpHandler的內容都不是很了解,這三個也是ASP.NET相對基礎的內容,晚上特地花點時間針對HttpModule的內容進行補充,文中的理論知識都是從網上多方面整理,最后的實例是本人所寫的兩個小實例,主要是針對HttpModule的運用;
一:關於HttpModule理論知識
1:HttpModule概述
HttpModule是實現了IHttpModule接口的程序集。一般來說,我們可以將Asp.Net中的事件分成三個級別,最頂層是 應用程序級事件、其次是頁面級事件、最下面是控件級事件,事件的觸發分別與 應用程序周期、頁面周期、控件周期緊密相關。而 Http Module 的作用是與應用程序事件密切相關的。
注意:在http請求的處理過程中,只能調用一個HttpHandler,但可以調用多個HttpModule。
2:HttpModules作用:
ASP.NET請求處理過程是基於管道模型的,這個管道模型是由多個HttpModule和HttpHandler組成,當請求到達HttpModule的時候,系統還沒有對這個請求真正處理,但是我們可以在這個請求傳遞到處理中心(HttpHandler)之前附加一些其它信息,或者截獲的這個請求並做一些額外的工作,也或者終止請求等。HttpHandler處理完請求之后,我們可以再在相應的HttpModule中把請求處理的結果進行再次加工返回客戶端。
3:Http模塊可以向System.Web.HttpApplication對象注冊下面一系列事件:
AcquireRequestState 當ASP.NET運行時准備好接收當前HTTP請求的對話狀態的時候引發這個事件。
AuthenticateRequest 當ASP.NET 運行時准備驗證用戶身份的時候引發這個事件。
AuthorizeRequest 當ASP.NET運行時准備授權用戶訪問資源的時候引發這個事件。
BeginRequest 當ASP.NET運行時接收到新的HTTP請求的時候引發這個事件。
Disposed 當ASP.NET完成HTTP請求的處理過程時引發這個事件。
EndRequest 把響應內容發送到客戶端之前引發這個事件。
Error 在處理HTTP請求的過程中出現未處理異常的時候引發這個事件。
PostRequestHandlerExecute 在HTTP處理程序結束執行的時候引發這個事件。
PreRequestHandlerExecute 在ASP.NET開始執行HTTP請求的處理程序之前引發這個事件。在這個事件之后,ASP.NET 把該請求轉發給適當的HTTP處理程序。
PreSendRequestContent 在ASP.NET把響應內容發送到客戶端之前引發這個事件。這個事件允許我們在內容到達客戶端之前改變響應內容。我們可以使用這個 事件給頁面輸出添加用於所有頁面的內容。例如通用菜單、頭信息或腳信息。
PreSendRequestHeaders 在ASP.NET把HTTP響應頭信息發送給客戶端之前引發這個事件。在頭信息到達客戶端之前,這個事件允許我們改變它的內容。我們可以使用這個事件在頭信息中添加cookie和自定義數據。
ReleaseRequestState 當ASP.NET結束所搜有的請求處理程序執行的時候引發這個事件。
ResolveRequestCache 我們引發這個事件來決定是否可以使用從輸出緩沖返回的內容來結束請求。這依賴於Web應用程序的輸出緩沖時怎樣設置的。
UpdateRequestCache 當ASP.NET完成了當前的HTTP請求的處理,並且輸出內容已經准備好添加給輸出緩沖的時候,引發這個事件。這依賴於Web應用程序的輸出緩沖是如何設置的。
注意: BeginRequest和PreRequestHandlerExecute之間的事件是在服務器執行HttpHandler處理之前觸發。
PostRequestHandlerExecute和PreSendRequestContent之間的事件是在服務器執行Handler處理之后觸發。
4:HttpModule生命周期示意圖
5:HttpModule實現:
HTTP模塊是實現了System.Web.IhttpModule接口的類。IHttpModule接口的聲明:
public interface IHttpModule
{
void Init (HttpApplication context);
void Dispose ();
}
Init 方法:系統初始化的時候自動調用,這個方法允許HTTP模塊向HttpApplication 對象中的事件注冊自己的事件處理程序。
Dispose方法: 這個方法給予HTTP模塊在對象被垃圾收集之前執行清理的機會。此方法一般無需編寫代碼。
二:HttpModule實例(分別用兩個HttpModule來演示):
(1)第一個實例是演示實現站點所有頁面的頭部跟尾部都同時輸出相同的內容:
步驟一:我們新建一個類讓它繼承接口IHttpModule;並讓它實現兩個事件,用於分別輸出
using System.Web; /// <summary> ///TestModule 的摘要說明 /// </summary> public class TestModule:IHttpModule { public TestModule() { } public void Dispose() { throw new NotImplementedException(); } public void Init(HttpApplication context) { context.BeginRequest += new EventHandler(context_StartRequest); context.EndRequest += new EventHandler(context_EndRequest); } /// <summary> /// 所有頁面頭部顯示 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void context_StartRequest(object sender, EventArgs e) { HttpApplication ha = (HttpApplication)sender; ha.Response.Write("頁面加載前的內容"); } /// <summary> /// 所有頁面尾部顯示 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void context_EndRequest(object sender, EventArgs e) { HttpApplication ha = (HttpApplication)sender; ha.Response.Write("內容加載后的內容"); } }
步驟二:修改web.config 增加配置信息
<httpModules> <add name="TestModule" type="TestModule,App_Code"/> </httpModules>
name:模塊名稱,一般是類名
type:有兩部分組成,前半部分是命名空間和類名組成的全名,后半部分是程序集名稱,如果類是直接放在App_Code文件夾中,那程序名稱是App_Code。
步驟三:查看運行效果(其中中間是我們當前頁的內容):
(2)第二個實例是我們平時系統登錄功能,實例把用戶信息保存到Cookies中;在HttpModule進行統一判斷,解決以前每個頁面或者寫個父類來進行判斷的麻煩;
步驟一:首先我們同樣新建一個類LoginModule繼承自IHttpModule
using System.Web; public class LoginModule:IHttpModule { public LoginModule() { } public void Dispose() { throw new NotImplementedException(); } public void Init(HttpApplication context) { context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute); } void context_PreRequestHandlerExecute(object sender, EventArgs e) { HttpApplication ha = (HttpApplication)sender; string path = ha.Context.Request.Url.Segments[2].ToString(); //獲得訪問的頁面 bool IsLogingPage = path.ToLower().Equals("login.aspx"); //比較是否是Login.aspx 是就不進入 if (!IsLogingPage) { var CookiesDemo = ha.Context.Request.Cookies["HttpDemo"]; if ( CookiesDemo== null) { ha.Context.Response.Redirect("Login.aspx"); } } } }
步驟二:修改web.config
<httpModules> <add name="LoginModule" type="LoginModule,App_Code"/> </httpModules>
步驟三:在登錄頁Login.aspx 實現一個針對Cookie的寫入功能;
protected void Button1_Click(object sender, EventArgs e) { HttpCookie ck = new HttpCookie("HttpDemo"); ck.Values.Add("UserID", "踏浪帥"); Response.SetCookie(ck); Response.Redirect("Default.aspx"); }
步驟四:在首頁Default.aspx 實現一個清除Cookie的功能,達到一個退出的功能
protected void Button1_Click(object sender, EventArgs e) { ClearCookie("HttpDemo"); Server.Transfer("Login.aspx"); } public static void ClearCookie(string cookiename) { HttpCookie cookie = HttpContext.Current.Request.Cookies[cookiename]; if (cookie != null) { cookie.Expires = DateTime.Now.AddYears(-3); HttpContext.Current.Response.Cookies.Add(cookie); } }
效果:當沒有在Login.aspx實現登錄(寫入Cookie)而直接訪問首頁Default.aspx時系統會自動跳轉到Login.aspx;
希望本文對您有幫助,感謝您的閱讀;[源代碼下載]