HttpApplication處理對象與HttpModule處理模塊 (第三篇)


一、HttpApplication對象簡述

  在HttpRuntime創建了HttpContext對象之后,HttpRuntime將隨后創建一個用於處理請求的對象,這個對象的類型為HttpApplication。

  HttpRuntime管理一個定義在System.Web命名空間下的HttpApplicationFactory類的時候,HttpApplicationFactory通過工廠模式管理HttpApplication對象。在HttpApplicationFactory內部維護了一個HttpApplication對象池,使得被創建的HttpApplication對象可以被重復使用。但是,每一個HttpApplication對象每一次僅僅用於處理一個請求,這樣就不需要考慮HttpApplication中多個請求並發的處理問題了。

  在HttpApplication中,利用.Net中的事件機制,通過在處理過程中依次發出的多個事件,將這個處理過程分解為多個步驟,這個處理機制通常我們稱為處理管道。

  處理管道,就是處理復雜問題的時候,將處理的過程分解為多個處理步驟,我們將這種經過多個步驟的處理方式稱為處理管道。在.Net中,借助於事件的強大威力,我們可以通過處理管道將復雜的處理步驟封裝起來,通過事件將處理過程的多個步驟暴露給程序員,以便於程序員對管理管道進行擴展。

  HttpApplication處理管道示意圖:

  

二、HttpApplication暴露的事件

  但是,對於一個有着眾多事件的類來說,定義大量的事件意味着創建對象的時候需要付出創建事件的成本,定義多個事件,意味着在創建的對象中將會需要更多的存儲空間。System.ComponentModel.Component類中,提供了處理多個事件的基礎:Events屬性,它的類型為System.ComponentModel.EventHandlerList,這是一個線性的字段,當需要事件的時候,就通過key將事件保存到集合中,沒有對應的事件,就不會付出創建事件的成本,這樣,通過EventHandlerList可以在一個集合中管理多個事件對象,節省了事件對象占用的空間。

  1、System.ComponentModel.EventHandlerList

  該類的常用成員:

成員定義 說明
void AddHandler() 將一個委托加入到集合中,key為委托所對應事件的對象
void RemoveHandler() 刪除一個委托
Delegate this[Object key] 通過表示事件的Key取得對應的委托

  這個類在使用的時候很簡單,首先從Component派生一個類,這個類繼承Component的Events集合屬性。對於這個派生類所需要定義的每一個事件,在類中定義一個對應的作為key的對象,以后,通過這個key對象來訪問有Events集合管理的事件。當然,用一個類似字典的集合也能夠完成這個任務。

  下面試試這個類如何用:

namespace ComponentListTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //這里是Asp.net程序員寫的代碼,對於程序員而言,只需要寫處理事件就可以了
            ProcessPipeline process = new ProcessPipeline();
            process.StartProcess += new EventHandler(process_StartProcess);
            process.EndProcess += new EventHandler(process_EndProcess);
            process.Process();

            Console.ReadKey();
        }

        static void process_StartProcess(object sender, EventArgs e)
        {
            Console.WriteLine("開始事件執行");
        }

        static void process_EndProcess(object sender, EventArgs e)
        {
            Console.WriteLine("結束事件執行");
        }
    }

    public class ProcessPipeline : System.ComponentModel.Component
    {
        private static readonly object startEvent = new object();
        private static readonly object endEvent = new object();

        public event EventHandler StartProcess
        {
            add { this.Events.AddHandler(startEvent, value); }
            remove { this.Events.RemoveHandler(startEvent, value); }
        }
        public event EventHandler EndProcess
        {
            add { this.Events.AddHandler(endEvent, value); }
            remove { this.Events.RemoveHandler(endEvent, value); }
        }

        protected void OnStartProcess(EventArgs e)
        {
            if (this.Events[startEvent] != null)
            {
                (this.Events[startEvent] as EventHandler)(this, e);
            }
        }

        protected void OnEndProcess(EventArgs e)
        {
            if (this.Events[endEvent] != null)
            {
                (this.Events[endEvent] as EventHandler)(this, e);
            }
        }

        public void Process()
        {
            Console.WriteLine("事件開始順序執行!");
            this.OnStartProcess(EventArgs.Empty);
            this.OnEndProcess(EventArgs.Empty);
        }
    }
}

  HttpApplication對象是Asp.net中處理請求的重要對象,但是,這種類型的對象實例不是由程序員來創建,而是由Asp.net幫助我們創建。為了便於擴展處理,Asp.net暴露了大量的事件給程序員,這些事件按照固定的處理順序依次觸發,程序員通過編寫事件處理方法就可以自定義每一個請求的擴展處理過程。

  HttpApplication的19個標准事件如下:

事件名稱 說明
BeginRequest Asp.net處理的第一個事件,表示處理的開始
AuthenticateRequest 驗證請求,一般用來取得請求用戶的信息
PostAuthenticateRequest 已經獲取請求用戶的信息
AuthorizeRequest 授權,一般用來檢查用戶的請求是否獲得權限
PostAuthorizeRequest 用戶請求已經得到授權
ResolveRequestCache 獲取以前處理緩存的處理結果,如果以前緩存過,那么,不必再進行請求的處理工作,直接返回緩存結果
PostResolveRequestCache 已經完成緩存的獲取操作
PostMapRequestHandler 已經根據用戶的請求,創建了處理請求的處理器對象
AcquireRequestState 取得請求的狀態,一般用於Session
PostAcquireRequestState 已經取得了Session
PreRequestHandlerExecute 准備執行處理程序
PostRequestHandlerExecute 已經執行了處理程序
ReleaseRequestState 釋放請求的狀態
PostReleaseRequestState 已經釋放了請求的狀態
UpdateRequestCache 更新緩存
PostUpdateRequestCache 已經更新了緩存
LogRequest 請求的日志操作
PostLogRequest 已經完成了請求的日志操作
EndRequest 本次請求處理完成

   2、事件簡要介紹

  Asp.net服務器對於每一次請求的處理過程都相同,都要經過這個HttpApplication處理管道。管道內部的處理過程是固定的,在服務器處理請求的各個階段,伴隨着處理的進行,依次觸發對應的事件,以便於程序員在處理的各個階段完成自定義的處理工作。

  1、最先觸發的事件是BeginRequest,這個事件標志着Asp.net服務器處理工作得開始,也是程序員在Asp.net中針對請求所能夠處理的第一個事件。

  2、開始處理請求后,第一個重要工作就是確定請求用戶的身份以實現安全機制,這個工作通過AuthenticateRequest和PostAuthenticateRequest兩個事件提供檢查當前請求用戶身份的機會。檢查后的用戶可以通過HttpContext的User屬性獲取到。如:

    if (HttpContext.Current.User.Identity.IsAuthenticated)
    {
        string UserName = HttpContext.Current.User.Identity.Name;
    }

  3、獲取用戶身份之后,將開始檢查權限的工作。如果沒有通過安全檢查,一般情況下,都跳過剩下的事件,直接出發EndRequest事件,結束請求的處理過程。

  4、當用戶通過了權限檢查,為了最快獲得結果,Asp.net將進行緩存檢查,看看是否可以從以前的緩存中直接取得處理的結果。

   5、當不能從緩存中獲取結果的時候,必須通過一次處理來計算出當前請求的結果。在Asp.net中,用於 處理請求以得到結果的對象稱為處理程序Handler,在Asp.net中提供了許多的處理程序,程序員也 可以自定義處理程序。為了處理這個請求,Asp.net必須按照匹配規則找到一個處理當前請求的處理 程序,PostMapRequestHandler事件表示Asp.net已經獲取了這個處理程序,HttpContext的Handler 屬性就表示這個處理程序對象。從上面的分析可以看到,HttpContext的Handler屬性到這里才有實 際的意義。

  6、雖然有了處理程序對象,但是還不能立即開始處理,因為會話狀態還未獲取,還需要先獲取Session然后才能獲取事件處理程序。
PreRequestHandlerExecute通知程序員,馬上開始調用處理程序了,有什么沒有准備好的趕緊准備。
  7、調用處理程序。
  8、在處理程序完成之后,服務器開始進行掃尾工作,PostRequestHandlerExecute事件通知程序員,Asp.net服務器的處理程序已經完成。在處理完成之后,由於在處理程序中,用戶可能修改了用戶特定的專屬數據,那么修改之后的用戶狀態數據可能需要進行序列化或者進行保存處理。ReleaseRequestState事件通知程序員需要釋放這些狀態數據,PostReleaseRequestState則表示已經釋放完成。
  9、在處理完成之后,如果希望將這次處理的結果緩存起來,以便在后繼的請求中可以直接使用這個結果,UpdateRequestCache事件提供了處理的機會,PostUpdateRequestCache則表示緩存已經更新完成。
  10、在Asp.net 4.0之后,新增加了兩個時間完成處理的日志工作:LogRequest表示將這次請求記入日志中,PostLogRequest表示完成了日志工作。
EndRequest是所有請求都要經過的最后一個HttpApplication處理管道的事件,也是程序員處理Asp.net處理請求中的最后一個機會。這個事件之后,處理的結果將被回應道瀏覽器,完成Asp.net服務器的處理工作。

三、HttpContext狀態管理

  HttpContext通過屬性User和Handler傳遞了當前請求的用戶和處理請求所使用的處理程序信息。如果我們還需要從HttpApplication前面的事件向后面的事件處理程序傳遞一些參數,那么可以通過HttpContext的Items屬性來完成。

  HttpContext類中定義了一個Items屬性,這是一個字典,定義如下:

public IDictionary Items{ get; }

  由於HttpContext對象貫穿整個HttpApplication的處理過程,所以,可以借助於這個屬性,從處理過程的前面的步驟中,將數據傳遞給后面的處理步驟,而不需要通過方法的參數或者對象的成員,這種傳遞參數的方式稱為基於HttpContext的狀態管理。

  這種狀態管理方式是Asp.net中周期最短的狀態管理方式,因此有着極高的內存使用效率,但是僅僅能夠用在服務器端的一次處理過程中。

四、處理HttpApplication事件

  HttpApplication提供了基於事件的擴展機制,允許程序員借助於處理管道中的事件進行處理過程擴展。由於HttpApplication對象是由Asp.net基礎架構來創建和維護的,那么,如何才能獲取這個對象的引用,以便於注冊HttpApplication對象的事件處理,在Asp.net中,提供了兩種方式來解決這個問題:IHttpModule方式和golbal.asax方式。這兩種方式的核心都是IHttpModule接口。

  1、通過IHttpModule創建HttpApplication的事件處理程序

  在Asp.net中,創建在System.Web命名空間下的IHttpModule接口專門用來定義HttpApplication對象的事件處理。實現IHttpModule接口的類稱為HttpModule(Http模塊)。

  IHttpModule接口的定義如下,其中僅僅包含兩個成員:

public interface IHttpModule
{
    void Dispose();
    void Init(HttpApplication context)
}

  其中,Dispose方法用於回收Module所使用的非托管資源,如果沒有的話,直接返回即可。

  最重要的是Init方法,可以看到,這個方法接收一個HttpApplication類型的參數,在Asp.net中,每當創建一個HttpApplication對象實例,將遍歷注冊的HttpModule類型,通過反射,依次每個注冊HttpModule類型的一個實例對象,並將這個HttpApplication實例通過Init方法傳遞給各個HttpModule,這樣HttpModule就可以在第一時間完成針對HttpApplication對象的事件注冊了。

  例如:希望寫一個處理PostAuthenticateRequest事件的HttpModule,那么可以完成如下事件的注冊:

public void Init(System.Web.HttpApplication application)
{
    application.PostAuthenticateRequest += new EventHandler(Application_PostAuthenticateRequest);
}

  2、注冊HttpModule

  在Asp.net中,實現IHttpModule接口只是實現HttpModule的第一步,在Asp.net中所使用的HttpModule還必須在網站配置文件中進行注冊才能真正生效,並在Asp.net中使用。

  配置文件有3個級別,詳細可在配置文件系列中找到:http://www.cnblogs.com/kissdodog/category/468516.html

  下面以web.config示例進行說明如何注冊HttpModule:

  system.web配置元素的子元素httpModules用來配置網站所使用的HttpModule;httpModules的子元素add用來增加一個新的HttpModule;clear將清除前面注冊的所有HttpModule。

  add元素有兩個必選的屬性name和type,簡介如下:

  • name表示這個HttpModule在程序中的名字,在網站應用程序中,可以通過這個名字來找到HttpModule對象的引用。HttpApplication的Modules屬性表示這個對象所關聯的所有HttpModule對象,通過這個name作為索引器,可以找到對應的HttpModule對象。
  • type表示HttpModule對象的類型名,Asp.net網站可以使用這個類型名,通過反射來動態創建HttpModule對象。類型的寫法就是反射中要求的類型名稱寫法,如果這個類定義在網站中,那么,就是一個包含命名空間的類的全名,否則,在全名的后面,使用逗號(,)分隔,還需要跟上類型所在的程序集的名稱,這個程序集的名稱不需要包含.dll擴展名。

  對於IIS7.0來說,需要在配置文件的system.webServer配置節中注冊HttpModule。注意此時的配置元素名稱變為了modules。在IIS7.0中,可以為MapRequestHandler,LogRequest和PostLogRequest事件添加處理程序。

  只要在IIS7.0集成模式下運行並且與.Net Framework3.0或更高版本一起運行的應用程序,才可以支持這些事件。

<system.webServer>
    <modules>
      <add name="ModuleExample" type="Samples.ModeleExample">
    </modules>
</system.webServer>

  3、非配置文件的方式注冊HttpModule

  在Asp.net4.0中,可以不修改配置文件也能達到完成Moudle注冊的目的。從.Net 3.5開始,新提供的PreApplicationStartMethodAttribute特征可以應用在程序集上,使得自定義的網站初始化代碼可以在Web應用程序的Application_Start初始化環節之前就執行。這個步驟甚至在動態編譯和執行Application_Start之前。對於每個程序集,可以定義一次。特征的定義如下:

[AttributeUsageAttribute(AttributeTargets.Assembly,AllowMultiple = false)]
public sealed class PreApplicationStartMethodAttribute:Attribute
{
    public Type Type{ get; }
    public string MethodName{ get; }
    ...
}

  Type用來指定定義了初始化方法的類型,MethodName用來指定將要執行的初始化方法。

  這樣,可以不在配置文件中固定配置HttpModule,而是定義一個方法,這個方法可以返回需要動態注冊的HttpModule,將這個方法以委托的形式登記在一個集合中。在網站啟動之后,每當HttpApplicationFactory創建一個HttpApplication對象,完成正常注冊的HttpModule創建及初始化之后,再來創建我們動態注冊的這些HttpModule。

  .

  .

  .

  .

  .

  暫時忽略這些東東,先寫下面的

  4、常見的HttpModule

  在Asp.net中,已經預定義了許多HttpModule,甚至已經在服務器的網站配置文件中進行了注冊,在系統文件夾C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\web.config中看到已經注冊的HttpModule如下:

<httpModules>
    <add name="OutputCache" type="System.Web.Caching.OutputCacheModule" />
    <add name="Session" type="System.Web.SessionState.SessionStateModule" />
    <add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule" />
    <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
    <add name="PassportAuthentication" type="System.Web.Security.PassportAuthenticationModule" />
    <add name="RoleManager" type="System.Web.Security.RoleManagerModule" />
    <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
    <add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule" />
    <add name="AnonymousIdentification" type="System.Web.Security.AnonymousIdentificationModule" />
    <add name="Profile" type="System.Web.Profile.ProfileModule" />
    <add name="ErrorHandlerModule" type="System.Web.Mobile.ErrorHandlerModule, System.Web.Mobile, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    <add name="ServiceModel" type="System.ServiceModel.Activation.HttpModule, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" />
    <add name="ScriptModule-4.0" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</httpModules>

  主要的HttpModule的解釋如下:

  1、OutputCacheModule完成Asp.net的輸出緩存管理工作:

  OutputCacheModule的配置參數通過system.web配置元素的caching子元素的outputCache元素進行定義。當啟用輸出緩存之后(啟用還是通過配置文件,下同),OutputCacheModule將注冊HttpApplication的ResolveRequestCache和UpdateRequestCache兩個事件完成輸出緩存的管理。

  2、SessionStateModule完成Session的管理工作:

  這個Module的配置參數通過配置文件中的system.web配置元素的sessionState子元素進行配置。當啟用Session狀態管理之后,SessionStateModule將注冊HttpApplication的AcquireRequestState、ReleaseRequestState、EndRequest三個事件完成Session狀態的管理工作。

  3、ProfileModule提供個性化數據管理:
  這是一個自定義的類似於Session的會話狀態管理,但是,個性化數據的讀取和保存可以由程序員完全控制,並且提供了強類型的數據訪問方式。這個Module的配置參數在system.web的子元素profile中進行說明。當啟用了個性化數據管理之后,Module將注冊HttpApplication的AcquireRequestState和EndRequest事件處理。

  4、AnonymousIdentificationModule提供匿名用戶的標志:
  是否啟用匿名用戶標志在配置文件的system.web配置元素的子元素anonymousIdentification中定義,還可以配置匿名標識的管理方式。由於在AuthenticateRequest事件中將驗證用戶,獲取用戶名,所以這個Module注冊了PostAuthenticateRequest的事件處理,當用戶沒有經過驗證的時候,為用戶分配一個唯一的匿名標識。

  5、WindowsAuthenticationModule、FormsAuthenticationModule和PassportAuthenticationModule用來完成用戶的驗證工作。
它們通過配置文件中system.web的子元素authentication子元素定義,mode屬性用來指定網站當前使用的驗證方式,也就是哪一個Module將被用來完成驗證工作。在啟用驗證的情況下,FormsAuthenticationModule和PassportAuthenticationModule將注冊HttpApplication的AuthenticateRequest和EndRequest事件進行用戶的驗證處理。WindowsAuthenticationModule將注冊AuthenticateRequest的事件處理。

  6、RoleManagerModule、UrlAuthorizationModule、FileAuthorizationModule用來完成用戶的授權管理:

  授權管理的配置參數來自system.web的authorization子元素。UrlAuthorizationModule和FileAuthorizationModule注冊了HttpApplication的AuthorizeRequest事件處理,用來檢查Url和文件的訪問授權。RoleManagerModule在Url和文件訪問授權檢查通過之后,通過用戶的標識和角色來完成用戶的授權檢查,RoleManagerModule注冊了HttpApplication的PostAuthenticateRequest和EndRequest事件處理。

  5、HttpModule事件

  每個HttpModule也可以觸發自定義的事件,但是,處理這些HttpModule事件更加麻煩一些,因為這些HttpModule對象實例也不是我們自己創建的。

  一般情況下,通過HttpApplication的Modules屬性獲取特定的HttpModule,這個屬性的定義如下:

public HttpModuleCollection Modules{ get; }

  可以使用定義HttpModule時候的name作為索引來獲取對應的HttpModule。例如,獲取前面定義的HttpModule對象的引用:

application.Modules["online"]

  然后就可以定義這個HttpModule的事件處理了。

  6、通過global.asax創建HttpApplication的事件處理程序

  在Visual Studio中創建的Asp.net項目中的Global.asax代碼如下:

    public class Global : System.Web.HttpApplication
    {

        void Application_Start(object sender, EventArgs e)
        {
            // 在應用程序啟動時運行的代碼

        }

        void Application_End(object sender, EventArgs e)
        {
            //  在應用程序關閉時運行的代碼

        }

        void Application_Error(object sender, EventArgs e)
        {
            // 在出現未處理的錯誤時運行的代碼

        }

        void Session_Start(object sender, EventArgs e)
        {
            // 在新會話啟動時運行的代碼

        }

        void Session_End(object sender, EventArgs e)
        {
            // 在會話結束時運行的代碼。 
            // 注意: 只有在 Web.config 文件中的 sessionstate 模式設置為
            // InProc 時,才會引發 Session_End 事件。如果會話模式設置為 StateServer 
            // 或 SQLServer,則不會引發該事件。

        }
    }

  下面給出一個HttpModule捕捉異常的示例,在Application:

    protected void Application_Error()
    {
        var error = Server.GetLastError();
        var code = (error is HttpException) ? (error as HttpException).GetHttpCode() : 500;

        //如果不是HttpException記錄錯誤信息
        if (code != 404)
        {
            //此處郵件或日志記錄錯誤信息
        }

        Response.Write("出錯");
        Server.ClearError();

        string path = Request.Path;
        Context.RewritePath(string.Format("~/Errors/Http{0}", code), false);
        IHttpHandler httpHandler = new MvcHttpHandler();
        httpHandler.ProcessRequest(Context);
        Context.RewritePath(path, false);
    }

  這樣,就不用把try{}catch{}寫得整個系統都是了!

  7、global.asax中HttpApplication事件的自動注冊

  在global.asax中,針對HttpApplication的事件處理,可以通過定義特殊命名的方法來實現。首先,這些方法必須符合System.EventHandler,因為所有的HttpApplication管道事件都使用這個委托定義。第二,方法的作用域必須是public。第三,方法的命名格式必須如下:Application_注冊的事件名稱。按照這種命名方法定義在global.asax中的方法將被自動注冊到對應的事件中。

  例如,希望在global.asax中注冊PostAuthenticateRequest事件處理,那么在global.asax中應該定義一個如下的方法:

    void Application_PostAuthenticateRequest(object sender, EventArgs e)
    {
        Response.Write("驗證通過事件!");
    }

  這對所有請求都有效,來看效果:

  

  8、特殊的HttpApplication事件處理

  通過global.asax文件,可以簡單地完成一些特殊的事件處理,只要按照特定的命名形式,就可以使定義的方法自動注冊到對應的事件中。在Asp.net中,有些事件甚至只能通過global.asax來完成處理。

  1、Start事件

  這個不是HttpApplication處理管道中的事件,當網站啟動后,第一次請求到達網站之后,Asp.net網站將首先觸發一次這個事件,而且在網站的整個生命周期中,也僅僅觸發一次。由System.Web.HttpApplicationFactory對象觸發,所以,也不能通過HttpApplication對象來獲取相關的請求參數。在這個事件處罰的時候,第一次請求的上下文對象HttpContext也已經創建,所以,可以通過HttpContext.Current獲取第一次的上下文請求對象,然后通過這個上下文對象來獲取相關信息。

  由於這個事件在網站第一次請求的時候觸發,所以非常適合針對網站全局的數據進行初始化工作,在Asp.net MVC中,RouteTablle就是在這個事件中創建的。

  2、End事件

當網站應用程序被關閉的時候,將觸發這個事件。

  3、Error事件

  當網站應用程序出現錯誤,或者處理過程中出現未捕獲的異常時,HttpApplication將拋出這個事件 。

  這個事件的事件源是HttpApplication,當前的異常信息可以通過HttpApplication的Server屬性獲取HttpServerUtility的對象實例來完成。HttpServerUtility對象的GetLasError()方法將返回最后一次的異常,這個方法的定義如下:

public Exception GetLastError();

  這個異常是一個經過包裝的異常,它的InnerException屬性指向網站最后一次拋出的未處異常。

  常見的處理如下:

    void Application_Error(object sender, EventArgs e) 
    {
        HttpServerUtility server = (sender as HttpApplication).Server;
        Exception exception = server.GetLastError().InnerException;
        //針對異常的處理
        Response.Write("異常信息:" + exception.Message);
        //清理這個異常
        server.ClearError();
    }

  模擬輸出一個異常:

    protected void Page_Load(object sender, EventArgs e)
    {
        throw new Exception("模擬異常");
    }

  輸出如下:

  

  4、Session的Start事件

  當Asp.net每次創建了一個新的Session后,換句話說,創建了一個新的SessionID之后,就會觸發Session的Start事件。需要注意到,在Asp.net中,支持會話的HttpModule在配置文件中注冊的name就是Session。

  5、Session的End事件

  當一個Session過期之后,或者通過調用Abandon方法被丟棄之后,將會觸發Session的End事件。這個事件的事件源實際上是SessionStateModule,而不是HttpApplication。需要注意的是,關閉瀏覽器不會導致Session的End事件。而且,如果Session的管理模式是StateServer或者SQLServer的話,將不會觸發這個事件。

  6、HttpModule的事件注冊

  從Session的處理可以看出,對於注冊到網站中的HttpModule,如果這些Module也會拋出事件,而我們希望能夠處理這些HttpModule事件的時候,可以在global.asax通過定義如下名稱形式的方法來處理HttpModule的事件。

HttpModule注冊名稱_事件名稱

  HttpApplication_BeginRequest(BeginRequest是19個事件的名稱)。當然,方法必須首先要符合事件的委托定義。

  在Asp.net 2.0之后,提供了匿名用戶的標識支持,這是通過一個注冊名為AnonymousIdentification的HttpModule實現的,它同事提供了一個名為Creating的事件,定義事件的委托如下:

public delegate void AnonymousIdentificationEventHandler(object sender,AnonymousIdentificationEventArgs e)

  那么,在global.asax中,可以定義如下命名形式的方法來處理這個事件。

public void AnonymousIdentificaton_Creating(object sender,AnonymousIdentificationEventArgs args)
{

}

  例如個性化數據Profile的事件處理。個性化數據是通過注冊名為Profile的HttpModule進行處理的,它的實際類型為ProfileModule,這個類提供了一個名為MigrateAnonymous的合並匿名用戶數據的事件,這個事件的委托定義如下:

public delegate void ProfileMigrateEventHandler(object sender,ProfileMigrateEventArgs)

  所以,可以在global.asax中定義如下形式的方法進行處理。

public void Profile_OnMigrateAnonymous(object sender,ProfileMigrateEventArgs args)
{
    ProfileCommon anonymousProfile = Profile.GetProfile(args.AnonymousID);
    ProfileManager.DeleteProfile(args.AnonymousID);
    AnonymousIdentificationModule.ClearAnonymousIdentifier();
    Membership.DeleteUser(args.AnonymousID,true);
}

五、兩個特殊事件

  1、PreSendRequestHeaders

  當准備通過HttpResponse回應發送HTTP的Header之前,HttpApplication將會觸發PreSendRequestHeaders事件。在這個事件中,可以根據發送的Header來動態設置一些參數,比如,如果通過Content-Type參數獲知發送的內容是text/html網頁,那么,可以通過啟用輸出的壓縮來提高網絡的傳輸速度。這個操作可以通過設置一個特殊的Header來通知瀏覽器。

  2、PreSendRequestContent

  當准備通過HttpResponse回應發送HTTP的Body內容之前,HttpApplication將會觸發PreSendRequestContent事件。如果配置了輸出到客戶端的壓縮,那么可以在這個事件中包裝輸出到瀏覽器的流以實現輸出的壓縮。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM