HttpModule的工作過程:
HttpModule是向實現類提供模塊初始化和處置事件的,當一個http請求到達httpModule時,整個Asp.Net Framework系統還沒有對這個Http請求做任何處理,也就是說此時對於Http請求來說,httpModule是http請求的必經之路,所以可以在這個http請求傳遞到真正的請求處理中心(HttpHandler)之前附加一些需要的信息在這個http請求信息之上,或者針對截獲的這個http請求做一些額外的工作,或者在某些情況下乾脆終止滿足一些條件的請求,從而起到了一個Filter過濾器的作用
深入瞭解HttpModule
一個HTTP請求在HttpModule容器的傳遞過程中,會在某一時刻(ResolveRequestCache事件)將這個HTTP請求傳遞給HttpHandler容器。在這個事件之後,HttpModule容器會建立一個HttpHandler的入口實例,但是此時並沒有將HTTP請求控制權交出,而是繼續觸發AcquireRequestState事件以及PreRequestHandlerExcute事件。在PreRequestHandlerExcute事件之後,HttpModule窗口就會將控制權暫時交給HttpHandler容器,以便進行真正的HTTP請求處理工作。
而在HttpHandler容器內部會執行ProcessRequest方法來處理HTTP請求。在容器HttpHandler處理完畢整個HTTP請求之後,會將控制權交還給HttpModule,HttpModule則會繼續對處理完畢的HTTP請求信息流進行層層的轉交動作,直到返回到客戶端爲止。
深入瞭解HttpModule
一個HTTP請求在HttpModule容器的傳遞過程中,會在某一時刻(ResolveRequestCache事件)將這個HTTP請求傳遞給HttpHandler容器。在這個事件之後,HttpModule容器會建立一個HttpHandler的入口實例,但是此時並沒有將HTTP請求控制權交出,而是繼續觸發AcquireRequestState事件以及PreRequestHandlerExcute事件。在PreRequestHandlerExcute事件之後,HttpModule窗口就會將控制權暫時交給HttpHandler容器,以便進行真正的HTTP請求處理工作。
而在HttpHandler容器內部會執行ProcessRequest方法來處理HTTP請求。在容器HttpHandler處理完畢整個HTTP請求之後,會將控制權交還給HttpModule,HttpModule則會繼續對處理完畢的HTTP請求信息流進行層層的轉交動作,直到返回到客戶端爲止。
示例2:驗證HttpModule生命週期
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
namespace MyHttpModule
{
public class ValidaterHttpModule : IHttpModule
{
#region IHttpModule 成員
public void Dispose()
{}
public void Init(HttpApplication application)
{
application.BeginRequest += new EventHandler(application_BeginRequest);
application.EndRequest += new EventHandler(application_EndRequest);
application.PreRequestHandlerExecute += new EventHandler(application_PreRequestHandlerExecute);
application.PostRequestHandlerExecute += new EventHandler(application_PostRequestHandlerExecute);
application.ReleaseRequestState += new EventHandler(application_ReleaseRequestState);
application.AcquireRequestState += new EventHandler(application_AcquireRequestState);
application.AuthenticateRequest += new EventHandler(application_AuthenticateRequest);
application.AuthorizeRequest += new EventHandler(application_AuthorizeRequest);
application.ResolveRequestCache += new EventHandler(application_ResolveRequestCache);
application.PreSendRequestHeaders += new EventHandler(application_PreSendRequestHeaders);
application.PreSendRequestContent += new EventHandler(application_PreSendRequestContent);
}
void application_PreSendRequestContent(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_PreSendRequestContent
");
}
void application_PreSendRequestHeaders(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_PreSendRequestHeaders
");
}
void application_ResolveRequestCache(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_ResolveRequestCache
");
}
void application_AuthorizeRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_AuthorizeRequest
");
}
void application_AuthenticateRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_AuthenticateRequest
");
}
void application_AcquireRequestState(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_AcquireRequestState
");
}
void application_ReleaseRequestState(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_ReleaseRequestState
");
}
void application_PostRequestHandlerExecute(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_PostRequestHandlerExecute
");
}
void application_PreRequestHandlerExecute(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_PreRequestHandlerExecute
");
}
void application_EndRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_EndRequest
");
}
void application_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.Context.Response.Write("application_BeginRequest
");
}
#endregion
}
}
多個自定義的Http Module的運作
從運行結果可以看到,在web.config文件中引入自定義HttpModule的順序就決定了多個自定義HttpModule在處理一個HTTP請求的接管順序。注:系統默認那幾個HttpModule是最先衩ASP.NET Framework所加載上去的。
如果我們把上面的兩個httpMudel都註冊在web.config中,輸出的結果是
我來自自定義HttpModule中的BeginRequest
application_BeginRequest
application_AuthenticateRequest
application_AuthorizeRequest
application_ResolveRequestCache
application_AcquireRequestState
application_PreRequestHandlerExecute
窗體頂端
窗體底端
application_PostRequestHandlerExecute
application_ReleaseRequestState
我來自自定義HttpModule中的EndRequest
application_EndRequest
application_PreSendRequestHeaders
application_PreSendRequestContent
我們可以發現不同的HttpMudel模塊是並進執行的,相同的方法會在一起執行,
在HttpModule中終止此次的HTTP請求
可以利用HttpModule通過調用HttpApplication.CompleteRequest()方法實現當滿足某一個條件時終止此次的HTTP請求。
需要注意的是,即使調用了HttpApplication.CompleteRequest()方法終止了一個HTTP請求,ASP.NET Framework仍然會觸發HttpApplication後面的這3個事件:EndRequest事件、PreSendRequestHeaders事件、PreSendRequestContent事件。
如果存在多個自定義的HttpModule的話,當Module1終止了一個HTTP請求,這個HTTP請求將不會再觸發Module2中相應的事件了,但Module2的最後三個事件仍會被觸發。
void application_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
application.CompleteRequest();
application.Context.Response.Write("application_BeginRequest
");
}
輸出的結果:
我來自自定義HttpModule中的BeginRequest
application_BeginRequest
我來自自定義HttpModule中的EndRequest
application_EndRequest
application_PreSendRequestHeaders
application_PreSendRequestContent
所以我們可以通過httpMudel對所有的請求進行監聽,對不符合的請求都可以做出相應的處理,從上面的圖中我們也可以看出http請求的執行過程,最終都會交個httpHandler去處理,然後在通過httpMudel返回到客戶端
同HttpHandler對應來看,這些事件,有些在HttpHandler之前發生,有些在HttpHandler處理完後發生。瞭解事件發生的順序非常重要,因爲,服務器端的對象在不同的時間段有着不同的表現。例子之一是Session的使用。不是所有的事件中都能對Session進行處理,而只能在有限的幾個事件中進行處理。詳細的過程可以參考下面的HTTP Request處理生命週期圖。
上面的這個圖又一次展示了它的用處,在平時的開發中,我們可以使用httpMudel開發權限管理系統,比如後臺,不是每一個人都可以知道url就進入到系統中,要在登錄的時候授權限纔可以,我們這個時候就可以在httpMudel中去處理是否授權,其他的如過濾危險字符串,防止sql注入,在這裏就不在一一介紹了,下面就來看看httpHandler類
概述
HttpHandler是一個HTTP請求的真正處理中心,也正是在這個HttpHandler容器中,ASP.NET Framework才真正地對客戶端請求的服務器頁面做出編譯和執行,並將處理過後的信息附加在HTTP請求信息流中再次返回到HttpModule中。
IHttpHandler如何處理HTTP請求
當一個HTTP請求經同HttpModule容器傳遞到HttpHandler容器中時,ASP.NET Framework會調用HttpHandler的ProcessRequest成員方法來對這個HTTP請求進行真正的處理。以一個ASPX頁面爲例,正是在這裏一個ASPX頁面才被系統處理解析,並將處理完成的結果繼續經由HttpModule傳遞下去,直至到達客戶端。
對於ASPX頁面,ASP.NET Framework在默認情況下是交給System.Web.UI.PageHandlerFactory這個HttpHandlerFactory來處理的。所謂一個HttpHandlerFactory,所謂一個HttpHandlerFactory,是指當一個HTTP請求到達這個HttpHandler Factory時,HttpHandlerFactory會提供出一個HttpHandler容器,交由這個HttpHandler容器來處理這個HTTP請求。
一個HTTP請求都是最終交給一個HttpHandler容器中的ProcessRequest方法來處理的。
public class MyFirstHandler : IHttpHandler,IRequiresSessionState
{
#region IHttpHandler 成員
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
context.Response.Write("
Hello HttpHandler
");context.Session["Test"] = "測試HttpHandler容器中調用Session";
context.Response.Write(context.Session["Test"]);
}
#endregion
}
}
在Web.config中加入如下配置:
從上面的代碼中可以看出需要實現IsReusable屬性和ProcessRequest方法,其中IsReusable屬性表示是否有好重用該Httphandler,而ProcessRequest測試請求最終的處理方法,該方法需要一個HttpContext實例作爲參數,用於在httpMudel與httphandler之間傳遞參數,也可以用於保持某個完整請求的相應的信息!
在實現很多功能中,我們都可以使用,比如圖片加水印,防止盜鏈等!