HttpModule是向實現類提供模塊初始化和處置事件。當一個HTTP請求到達HttpModule時,整個ASP.NET Framework系統還並無對這個HTTP請求作任何處理,也就是說此時對於HTTP請求來說,HttpModule是一個HTTP請求的「必經之路」,因此能夠在這個HTTP請求傳遞到真正的請求處理中心(HttpHandler)以前附加一些須要的信息在這個HTTP請求信息之上,或者針對截獲的這個HTTP請求信息做一些額外的工做,或者在某些狀況下乾脆終止知足一些條件的HTTP請求,從而能夠起到一個Filter過濾器的做用。web
說明:
(1)、客戶端瀏覽器向服務器發出一個http請求,此請求會被inetinfo.exe進程截獲,而後轉交給aspnet_isapi.dll進程,接着它又經過Http Pipeline的管道,傳送給aspnet_wp.exe這個進程,接下來就到了.net framework的HttpRunTime處理中心,處理完畢後就發送給用戶瀏覽器。
(2)、當一個http請求被送入到HttpRuntime以後,這個Http請求會繼續被送入到一個被稱之爲HttpApplication Factory的一個容器當中,而這個容器會給出一個HttpApplication實例來處理傳遞進來的http請求,然後這個Http請求會依次進入到以下幾個容器中:HttpModule --> HttpHandler Factory --> HttpHandler。當系統內部的HttpHandler的ProcessRequest方法處理完畢以後,整個Http Request就被處理完成了,客戶端也就獲得相應的東東了。
(3)完整的http請求在asp.net framework中的處理流程:
HttpRequest-->inetinfo.exe->ASPNET_ISAPI.DLL-->Http Pipeline-->ASPNET_WP.EXE-->HttpRuntime-->HttpApplication Factory-->HttpApplication-->HttpModule-->HttpHandler Factory-->HttpHandler-->HttpHandler.ProcessRequest() api
也就是說一個HTTP請求在HttpModule容器的傳遞過程當中,會在某一時刻(ResolveRequestCache事件)將這個HTTP請求傳遞給HttpHandler容器。在這個事件以後,HttpModule容器會創建一個HttpHandler的入口實例,可是此時並無將HTTP請求控制權交出,而是繼續觸發AcquireRequestState事件以及PreRequestHandlerExcute事件。在PreRequestHandlerExcute事件以後,HttpModule窗口就會將控制權暫時交給HttpHandler容器,以便進行真正的HTTP請求處理工做。瀏覽器
而在HttpHandler容器內部會執行ProcessRequest方法來處理HTTP請求。在容器HttpHandler處理完畢整個HTTP請求以後,會將控制權交還給HttpModule,HttpModule則會繼續對處理完畢的HTTP請求信息流進行層層的轉交動做,直到返回到客戶端爲止。
PS:紅色的HttpApplication實例在HttpModule的Init方法中會用到。緩存
(4)若是想在中途截獲一個httpRequest並作些本身的處理,就應該在HttpRuntime運行時內部來作到這一點,確切的說是在HttpModule這個容器中來實現。服務器
負責監聽HttpRequest,同時對HttpRequest增添或者過濾掉一部份內容。也就是說,當一個HTTP請求到達HttpModule時,整個ASP.NET Framework系統還並無對這個HTTP請求作任何處理,也就是說此時對於HTTP請求來說,HttpModule是一個HTTP請求的「必經之路」,因此能夠在這個HTTP請求傳遞到真正的請求處理中心(HttpHandler)以前附加一些須要的信息在這個HTTP請求信息之上,或者針對截獲的這個HTTP請求信息做一些額外的工做,或者在某些狀況下乾脆終止知足一些條件的HTTP請求,從而能夠起到一個Filter過濾器的做用。
HttpModule實現了接口IHttpModule,咱們能夠自定義實現該接口的類,從而取代HttpModule。
asp.net默認的HttpModule以下:app
System.Web.SessionState.SessionStateModule;
System.Web.Security.WindowsAuthenticationModule;
System.Web.Security.FormsAuthenticationModule;
System.Web.Security.PassportAuthenticationModule;
System.Web.Security.UrlAuthorizationModule;
System.Web.Security.FileAuthorizationModule;
要實現HttpModule,必須實現接口IHttpModule。下面是IHttpModule接口分析:asp.net
using System; namespace System.Web { public interface IHttpModule { // 銷燬再也不被HttpModule使用的資源 void Dispose(); // 初始化一個Module,爲捕獲HttpRequest作準備 void Init(HttpApplication context); } }
下面是本身的HttpModule:ui
using System; using System.Web; namespace ClassLibrary1 { public class MyHttpModule : IHttpModule { public void Dispose() { } public void Init(HttpApplication context) { context.BeginRequest += new EventHandler(Application_BeginRequest); context.EndRequest += new EventHandler(Application_EndRequest); } public void Application_BeginRequest(object sender, EventArgs e) { HttpApplication application = sender as HttpApplication; HttpContext context = application.Context; HttpResponse response = context.Response; response.Write("這是來自自定義HttpModule中有BeginRequest"); } public void Application_EndRequest(object sender, EventArgs e) { HttpApplication application = sender as HttpApplication; HttpContext context = application.Context; HttpResponse response = context.Response; response.Write("這是來自自定義HttpModule中有EndRequest"); } } }
web.configspa
<httpModules> <add name="myHttpModule" type="ClassLibrary1.MyHttpModule,ClassLibrary1"/> </httpModules>
default.aspx.cs .net
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { Response.Write("<br/><br/>來自Default.aspx頁面<br/>"); } }
HttpModule對HttpApplication實例進行處理,而HttpApplication有不少事件(對應不一樣的生命期),這樣就衍生出HttpModule內部事件機制和生命週期。
(1)、HttpModule的事件
BeginRequest | 指示請求處理開始 |
AuthenticateRequest | 封裝請求身份驗證過程 |
AuthorizeRequest | 封裝檢查是否能利用之前緩存的輸出頁面處理請求的過程 |
ResolveRequestCache | 從緩存中獲得相應時候觸發 |
AcquireRequestState | 加載初始化Session時候觸發 |
PreRequestHandlerExecute | 在Http請求進入HttpHandler以前觸發 |
PostRequestHandlerExecute | 在Http請求進入HttpHandler以後觸發 |
ReleaseRequestState | 存儲Session狀態時候觸發 |
UpdateRequestCache | 更新緩存信息時觸發 |
EndRequest | 在Http請求處理完成的時候觸發 |
PreSendRequestHenaders | 在向客戶端發送Header以前觸發 |
PreSendRequestConternt | 在向客戶端發送內容以前觸發 |
說明:
a、BenginRequest和EndRequest分別是HttpModule容器最開始的和最後的事件;
b、EndRequest以後還會觸發PreSendRequestHeaders事件和PreSendRequestContent事件,這不是在HttpModule外的兩個事件,表示HttpModule結束,即將開始向Client發送數據。
(2)、驗證HttpModule生命週期
與HttpHandler的交互:
說明:
a、HttpModule容器會將HttpRequest傳遞到HttpHandler容器,這個時間點是ResolveRequestCache事件
b、HttpModule容器會創建HttpHandler實例做爲入口——Session今後生效
c、觸發AcquireRequestState事件以及PreRequestHandlerExecute事件
d、HttpModule容器便將對HttpRequest的控制權轉讓給HttpHandler容器
e、HttpHandler容器處理HttpRequest——使用自身的ProcessRequest方法,將對其控制權又還給HttpModule容器——以後Session失效。
驗證生命週期代碼:
using System; using System.Collections.Generic; using System.Text; using System.Web; namespace MyHttpModule { public class ValidaterHttpModuleEvents : IHttpModule { public void Dispose() { } /// <summary> /// 驗證HttpModule事件機制 /// </summary> /// <param name="application"></param> public void Init(HttpApplication application) { application.BeginRequest += new EventHandler(application_BeginRequest); application.EndRequest += new EventHandler(application_EndRequest); application.AcquireRequestState += new EventHandler(application_AcquireRequestState); application.AuthenticateRequest += new EventHandler(application_AuthenticateRequest); application.AuthorizeRequest += new EventHandler(application_AuthorizeRequest); application.PreRequestHandlerExecute += new EventHandler(application_PreRequestHandlerExecute); application.PostRequestHandlerExecute += new EventHandler(application_PostRequestHandlerExecute); application.ReleaseRequestState += new EventHandler(application_ReleaseRequestState); application.ResolveRequestCache += new EventHandler(application_ResolveRequestCache); application.PreSendRequestHeaders += new EventHandler(application_PreSendRequestHeaders); application.PreSendRequestContent += new EventHandler(application_PreSendRequestContent); } private void application_BeginRequest(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; application.Context.Response.Write("application_BeginRequest<br/>"); } private void application_EndRequest(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; application.Context.Response.Write("application_EndRequest<br/>"); } private void application_PreRequestHandlerExecute(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; application.Context.Response.Write("application_PreRequestHandlerExecute<br/>"); } private void application_PostRequestHandlerExecute(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; application.Context.Response.Write("application_PostRequestHandlerExecute<br/>"); } private void application_ReleaseRequestState(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; application.Context.Response.Write("application_ReleaseRequestState<br/>"); } private void application_AcquireRequestState(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; application.Context.Response.Write("application_AcquireRequestState<br/>"); } private void application_PreSendRequestContent(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; application.Context.Response.Write("application_PreSendRequestContent<br/>"); } private void application_PreSendRequestHeaders(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; application.Context.Response.Write("application_PreSendRequestHeaders<br/>"); } private void application_ResolveRequestCache(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; application.Context.Response.Write("application_ResolveRequestCache<br/>"); } private void application_AuthorizeRequest(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; application.Context.Response.Write("application_AuthorizeRequest<br/>"); } private void application_AuthenticateRequest(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; application.Context.Response.Write("application_AuthenticateRequest<br/>"); } } }
<add name="HttpModule1" type="MyHttpModule.HttpModule1,MyHttpModule"/> <add name="HttpModule2" type="MyHttpModule.HttpModule2,MyHttpModule"/>
HttpModule1和HttpModule2模仿ValidaterHttpModuleEvents編寫(除了類名改變外,事件和方法不變),不貼代碼了。運行結果以下:
從運行結果能夠看到,在web.config文件中引入自定義HttpModule的順序就決定了多個自定義HttpModule在處理一個HTTP請求的接管順序。
(3)、利用HttpModule實現終止這次HttpRequest請求
在BeginRequest事件中,使用HttpApplication.CompleteRequest()方法能夠實現當知足必定條件時終止這次HttpRequest請求
using System; using System.Web; namespace ClassLibrary1 { public class MyHttpModule : IHttpModule { public void Dispose() { } public void Init(HttpApplication context) { context.BeginRequest += new EventHandler(Application_BeginRequest); } public void Application_BeginRequest(object sender, EventArgs e) { HttpApplication application = sender as HttpApplication; application.CompleteRequest(); application.Context.Response.Write("請求被終止"); } } }
說明:
a、對於一個HttpModule,在BeginRquest中終止,可是仍然會調用EndRequest事件,以及PreSendRequestHeaders事件和PreSendRequestContent事件。也能夠說是直接跳轉到EndRequest事件,而不會調用這期間的事件
b、若是有兩個HttpModule,在第一個HttpModule的BeginRequest中終止,僅僅不會調用第二個HttpModule的BeginRequest,但仍然會調用兩個EndRequest事件,以及PreSendRequestHeaders事件和PreSendRequestContent事件。看下面的圖示: