HttpModule是向實現類提供模塊初始化和處置事件。當一個HTTP請求到達HttpModule時,整個ASP.NET Framework系統還并沒有對這個HTTP請求做任何處理,也就是說此時對于HTTP請求來講,HttpModule是一個HTTP請求的“必經之路”,所以可以在這個HTTP請求傳遞到真正的請求處理中心(HttpHandler)之前附加一些需要的信息在這個HTTP請求信息之上,或者針對截獲的這個HTTP請求信息作一些額外的工作,或者在某些情況下干脆終止滿足一些條件的HTTP請求,從而可以起到一個Filter過濾器的作用。
首先你要實現IHttpModule接口這個接口只有兩個方法,一個是Init方法一個Dispose方法.

Code
using System;
namespace System.Web
{
// Summary:
// Provides module initialization and disposal events to the implementing class.
public interface IHttpModule
{
// Summary:
// Disposes of the resources (other than memory) used by the module that implements
// System.Web.IHttpModule.
void Dispose();
//
// Summary:
// Initializes a module and prepares it to handle requests.
//
// Parameters:
// context:
// An System.Web.HttpApplication that provides access to the methods, properties,
// and events common to all application objects within an ASP.NET application
void Init(HttpApplication context);
}
}
一個HTTP請求在HttpModule容器的傳遞過程中,會在某一時刻(ResolveRequestCache事件)將這個HTTP請求傳遞給HttpHandler容器。在這個事件之后,HttpModule容器會建立一個HttpHandler的入口實例,但是此時并沒有將HTTP請求控制權交出,而是繼續觸發AcquireRequestState事件以及PreRequestHandlerExcute事件。在PreRequestHandlerExcute事件之后,HttpModule窗口就會將控制權暫時交給HttpHandler容器,以便進行真正的HTTP請求處理工作。
而在HttpHandler容器內部會執行ProcessRequest方法來處理HTTP請求。在容器HttpHandler處理完畢整個HTTP請求之后,會將控制權交還給HttpModule,HttpModule則會繼續對處理完畢的HTTP請求信息流進行層層的轉交動作,直到返回到客戶端為止。
HttpModule過程在下面的事件:
1.BeginRequest 指示請求處理開始。
2.AuthenticateRequest PostAuthenticateRequest 封裝請求身份驗證過程。
3.AuthorizeRequest PostAuthorizeRequest 封裝請求授權過程。
4.ResolveRequestCache PostResolveRequestCache 封裝檢查是否能利用以前緩存的輸出頁面處理請求的過程。
5.PostMapRequestHandler 指示已發現用于處理請求的 HTTP 處理程序。
6.AcquireRequestState PostAcquireRequestState 封裝對請求會話狀態的檢索。
7.PostRequestHandlerExecute 指示用于處理請求的 HTTP 處理程序已執行。
8.ReleaseRequestState PostReleaseRequestState 封裝對請求會話狀態的發布。
9.UpdateRequestCache PostUpdateRequestCache 封裝檢查是否應對請求的資源的輸出進行緩存以備今后重復使用的過程。
10.EndRequest 指示請求處理結束。
可以利用HttpModule通過調用HttpApplication.CompleteRequest()方法實現當滿足某一個條件時終止此次的HTTP請求。需要注意的是,即使調用了HttpApplication.CompleteRequest()方法終止了一個HTTP請求,ASP.NET Framework仍然會觸發HttpApplication后面的這3個事件:EndRequest事件、PreSendRequestHeaders事件、PreSendRequestContent事件。
如果存在多個自定義的HttpModule的話,當Module1終止了一個HTTP請求,這個HTTP請求將不會再觸發Module2中相應的事件了,但Module2的最后三個事件仍會被觸發。

Code
public class CompleteRequestHttpModule : IHttpModule
{
#region IHttpModule 成員
public void Dispose()
{}
public void Init(HttpApplication application)
{
application.BeginRequest += new EventHandler(Application_BeginRequest);
}
void Application_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.CompleteRequest();
application.Context.Response.Write("請求被終止。");
}
#endregion
}
HttpModule示例:
過濾http請求

Code
///
/// 頁面訪問驗證模塊
///
public class AuthenticationModule : IHttpModule
{
#region IHttpModule Members
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.AcquireRequestState += new EventHandler(context_AcquireRequestState);
}
#endregion
private void context_AcquireRequestState(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
string path = context.Request.Path.ToLower();
// 只處理aspx文件,因為其他文件無法獲得Session對象,無法判斷是否已經登錄
if (path.EndsWith(".aspx"))
{
// 如果用戶沒有登錄就會返回false
if (!UserRules.Instance.IsCurrentUserLogined)
{
// 對于公共文件夾和根目錄的文件不做判斷
if (path.StartsWith("/" + AppSettings.PUBLICFOLDERNAME + "/")==false && !(path.LastIndexOf("/") == 0))
{
// 跳轉到公共頁面首頁
context.Response.Redirect(AppSettings.PUBLICLOGOUTFILENAME, false);
context.ApplicationInstance.CompleteRequest();
}
}
}
}
}
在web.confg中添加httpModules節點注冊事件
判斷瀏覽器的版本

Code
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
///
/// BrowserModule 的摘要說明
///
public class BrowserModule : IHttpModule
{
public BrowserModule()
{
//
// TODO: 在此處添加構造函數邏輯
//
}
#region IHttpModule 成員
public void Dispose()
{
}
public void Init(HttpApplication context)
{
//添加判斷事件
context.BeginRequest += new EventHandler(context_BeginRequest);
context.EndRequest += new EventHandler(context_EndRequest);
}
void context_EndRequest(object sender, EventArgs e)
{
if (isfalse)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Clear();//清空瀏覽器所有的內容
application.Context.Response.Output.Write("瀏覽器不符合要求");
}
}
public bool isfalse = false;//判斷瀏覽器是否符合要求
void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;//獲得實際發生事件的對象
HttpBrowserCapabilities browser = application.Context.Request.Browser;//獲得瀏覽器的相關信息
//獲得瀏覽器的名字 application.Context.Response.Output.Write(browser.Browser);
//獲得瀏覽器的版本號 application.Context.Response.Output.Write(browser.MajorVersion );
if (browser.Browser != "IE" || browser.MajorVersion < 7)//判斷瀏覽器的版本是否是IE5以上的
{
string strBrowserChooserPage = "";//創建變量裝載瀏覽器不符合條件后要導入的頁面
try
{
strBrowserChooserPage = ConfigurationManager.AppSettings["BrowserChooserPage"];//從配置文件中導入要瀏覽的頁面
}
catch (System.Configuration.ConfigurationErrorsException ex)
{
throw new Exception(string.Format("請正確配置web.config AppSetting[BrowserChooserPage]節點,系統錯誤提示:{0}", ex.Message));
}
catch (System.Exception ex)
{
throw ex;
}
isfalse = true;//為True的時候瀏覽器不符合要求,處理完context_BeginRequest事件后,最好在處理context_EndRequest事件的時候判斷是否合適
}
else
{
application.Context.Response.Output.Write("瀏覽器符合要求");
}
}
#endregion
}
注冊web.config事件
實現URL重寫

Code
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
///
/// UrlReWriteHttpModule 的摘要說明
///
public class UrlReWriteHttpModule : IHttpModule
{
public UrlReWriteHttpModule()
{
//
// TODO: 在此處添加構造函數邏輯
//
}
#region IHttpModule 成員
public void Dispose()
{
throw new Exception("The method or operation is not implemented.");
}
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
void context_BeginRequest(object sender, EventArgs e)
{
HttpContext context = (sender as HttpApplication).Context;
//string Url1 = context.Request.Path;
//string Url2 = context.Request.PathInfo;
//string Url3 = context.Request.Url.ToString();
//得到整個的網絡地址
string fullOrigionalpath = context.Request .Url.ToString();
if (fullOrigionalpath.Contains("/Books.aspx"))
{
context.RewritePath("Products.aspx?Category=Books");//重寫地址,重寫后地址欄中的顯示不變,但是真正返回的頁面是被重寫的頁面
}
else if (fullOrigionalpath.Contains("/DVDs.aspx"))
{
context.RewritePath("Products.aspx?Category=DVDs");
}
else if (fullOrigionalpath.Contains("/DVDs.aspx"))
{
context.RewritePath("Products.aspx?Category=CDs.aspx");
}
}
#endregion
}
注冊web.config事件
-------------------------------------------------完成------------------------------------------------
從上面的例子看出,其實是一個好簡單的實現方法,就是在init中注冊處理過程事件,把代碼寫完后,在web.congif中HttpModules注冊就完成了.
開發程序千變萬變, 通過這一方法可以編寫出好多合適自己用的功能,這需要大家去實踐了. 收集與整理,且當成長的回憶.