天天看點

Httphandle Httpmodule HttpHandler Factory 學習整理

ASP.NET Framework處理一個Http Request的流程:

    HttpRequest-->inetinfo.exe-->ASPNET_ISAPI.dll-->ASPNET_WP.exe-->HttpRuntime-->HttpApplication Factory-->HttpApplication-->HttpModule-->HttpHandler Factory-->HttpHandler-->HttpHandler.ProcessRequest()

在http請求的處理過程中,隻能調用一個HttpHandler,但可以調用多個HttpModule。但我們可以使用HttpHandler Factory來選擇使用哪個HttpHandler。

HttpModule

當一個HTTP請求到達HttpModule時,整個ASP.NET Framework系統還并沒有對這個HTTP請求做任何處理,也就是說此時對于HTTP請求來講,HttpModule是一個HTTP請求的“必經之路”,是以可以在這個HTTP請求傳遞到真正的請求進行中心(HttpHandler)之前附加一些需要的資訊在這個HTTP請求資訊之上,或者針對截獲的這個HTTP請求資訊作一些額外的工作,或者在某些情況下幹脆終止滿足一些條件的HTTP請求,進而可以起到一個Filter過濾器的作用。

一個HTTP請求在HttpModule容器的傳遞過程中,會在某一時刻(ResolveRequestCache事件)将這個HTTP請求傳遞給HttpHandler容器。在這個事件之後,HttpModule容器會建立一個HttpHandler的入口執行個體,但是此時并沒有将HTTP請求控制權交出,而是繼續觸發AcquireRequestState事件以及PreRequestHandlerExcute事件。在PreRequestHandlerExcute事件之後,HttpModule視窗就會将控制權暫時交給HttpHandler容器,以便進行真正的HTTP請求處理工作。

而在HttpHandler容器内部會執行ProcessRequest方法來處理HTTP請求。在容器HttpHandler處理完畢整個HTTP請求之後,會将控制權交還給HttpModule,HttpModule則會繼續對處理完畢的HTTP請求資訊流進行層層的轉交動作,直到傳回到用戶端為止。

完整的http請求在asp.net framework中的處理流程:

Httphandle Httpmodule HttpHandler Factory 學習整理

    HTTP子產品是實作了System.Web.IhttpModule接口的類。

    IHttpModule接口的聲明:

public interface IHttpModule

        {

            void Init (HttpApplication context); //初始化,事件注冊

            void Dispose ();

        }

Init 方法:系統初始化的時候自動調用,這個方法允許HTTP子產品向HttpApplication 對象中的事件注冊自己的事件處理程式。

Dispose方法: 這個方法給予HTTP子產品在對象被垃圾收集之前執行清理的機會。此方法一般無需編寫代碼。

    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應用程式的輸出緩沖是如何設定的。

HttpHandler

    HttpHandler是HTTP請求的進行中心,真正地對用戶端請求的伺服器頁面做出編譯和執行,并将處理過後的資訊附加在HTTP請求資訊流中再次傳回到HttpModule中。

    HttpHandler與HttpModule不同,一旦定義了自己的HttpHandler類,那麼它對系統的HttpHandler的關系将是“覆寫”關系。

    IHttpHandler接口聲明

public interface IHttpHandler

    {

        bool IsReusable { get; }

        public void ProcessRequest(HttpContext context); //請求處理函數

    }

Web.Config配置檔案

<httpHandlers>

       <add verb="*" path="*" type="ClassLibrary831.TestHandler,ClassLibrary831"></add>

      </httpHandlers>

Verb屬性:指定了處理程式支援的HTTP動作。*-支援所有的HTTP動作;“GET”-支援Get操作;“POST”-支援Post操作;“GET, POST”-支援兩種操作。

Path屬性:指定了需要調用處理程式的路徑和檔案名(可以包含通配符)。“*”、“*.aspx”、“showImage.aspx”、“test1.aspx,test2.aspx”

Type屬性:用名字空間、類名稱和程式集名稱的組合形式指定處理程式或處理程式工廠的實際類型。ASP.NET運作時首先搜尋bin目錄中的DLL,接着在GAC中搜尋。

IHttpHandler工廠

IHttpHandlerFactory的作用是對IHttpHandler進行管理。比如針對不同的兩個頁面需要使用兩個不同的HttpHandler進行處理時,使用IHttpHandlerFactory管理。

IHttpHandlerFactory接口的聲明:

public interface IHttpHandlerFactory

        {

            IHttpHandler GetHandler (HttpContext context,string requestType,string url,string pathTranslated);

            void ReleaseHandler (IHttpHandler handler);

        }

參數

context

類型: System.WebHttpContext

HttpContext 類的執行個體,它提供對用于為 HTTP 請求提供服務的内部伺服器對象(如 Request、Response、Session 和 Server)的引用。

requestType

類型: SystemString

用戶端使用的 HTTP 資料傳輸方法(GET 或 POST)。

virtualPath

類型: SystemString

所請求資源的虛拟路徑。

path

類型: SystemString

所請求資源的 PhysicalApplicationPath 屬性。

傳回值

類型: System.WebIHttpHandler

示例:

public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
{
    Request request = new Request(context, requestType, url);
    if (!(request.Extension == Utility.HandlerExtension))
    {
        throw new HttpException(0x193, "The type of page you have requested is not served because it has been explicitly forbidden. The extension '." + request.Extension + "' may be incorrect. Please review the URL below and make sure that it is spelled correctly.");
    }
    if (context.Request["_session"] != null)
    {
        if (context.Request["_session"] == "rw")
        {
            return new AjaxHandlerSessionStateRW();
        }
        if (context.Request["_session"] == "r")
        {
            return new AjaxHandlerSessionStateR();
        }
        if (context.Request["_session"] == "no")
        {
            return new AjaxHandler();
        }
    }
    if ((context.Session != null) && !context.Session.IsCookieless)
    {
        return new AjaxHandler();
    }
    return new AjaxHandlerSessionStateR();
}