HttpApplication,HttpModule,HttpContext及Asp.Net頁生命週期
IIS在接到一個新的http請求後,最終會呼叫asp.net_isapi.dll的ISAPI擴充套件(特指IIS6.0環境,iis7.0的應用程式池預設為整合方式,相對有所變化),然後傳遞到httpRuntime Pipe(http執行時管道),Asp.Net這時才開始執行(即HttpRunTime是Asp.Net真正的入口),HttpRunTime會為每個asp.net應用自動建立一個HttpApplication的例項,而該例項中又包含以下屬性:
注1
Application -->相當於傳統意義上asp時代的application物件,通常用於定義一個asp.net應用的全域性變數
Context -->HttpContext(上下文)類的例項【Asp.Net新增的】
Modules -->影響當前應用程式的HttpModule模組集合
Request -->類似於asp中的Request物件,通常用於接收一些特定的值(比如Request.Form或Request.QueryString)
Response -->類似於asp中的Response物件,通常用於向做頁面輸出指定內容(比如Resonse.Write)
Server -->類似於asp中的Server物件,通過它能獲得一些服務端的資訊(比如Server.MapPath)
Session -->類似於asp中的Session物件
User -->用於獲取使用者認證相關的安全資訊
從上面的屬性可以發現:很多其實在asp年代已在使用,只有Context,Modules,User這三個是Asp.Net新增的
HttpApplication類除了具備"注1"的幾個屬性外,還有自己的方法,這裡特別提一下Init方法和Dispose方法,這二個方法均可過載.
它們的呼叫時機為:
Init方法在Application_Start之後呼叫,而Dispose在Application_End之前呼叫,另外Application_Start在整個asp.net應用的生命週期內只激發一次(比如IIS啟動或網站啟動時),類似的Application_End也只有當asp.net應用程式關閉時被呼叫(比如IIS停止或網站停止時)
除了Application_Start和Application_End方法,HttpApplication還提供了以下事件:
這些事件包括前面提到的可過載的Init及Dispose方法,再加上Session對應的Session_Start與Session_End方法,均可直接在Global.ascx.cs中以Application_XXX的形式使用(因為Global.ascx.cs中定義的類Global本身就是繼承自HttpApplication的)
public class Global : System.Web.HttpApplication
再來看一下相對asp而言,新增的Context,Modules,User這三個屬性
Context:
Context即HttpContext類的例項,在幾乎整個aspx頁面生命週期中,Context上下文一直伴隨著各個環節向下傳遞
所以我們幾乎可以在web應用中的任何環節,用HttpContext.Current來引用到當前的上下文例項,從HttpContext的定義上,還可以發現Context本身的屬性中,又可以得到Application,ApplicationInstance,Profile,Response.Request...等物件的例項引用
回想一下:
public class Handler1 : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Write("Hello World");
}
public bool IsReusable
{
get
{
return false;
}
}
}
我們在使用一個ashx檔案時,ProcessRequest方法便是把當前上下文傳遞進來,進而通過context得到Response物件的引用,最終可以向頁面輸出任何想要的內容.
Modules:
每一個實現了IHttpModule介面的類,就可以被認為是Http模組元件,可以理解為http請求攔截器,攔截到http請求後,它能修改正在被處理的Context上下文,完事兒之後,再把控制權交還給管道,如果還有其它模組,則依次繼續處理,直到所有Modules集合中的HttpModule都“爽”完為止(注:可憐的http請求就這樣給各個httpModule輪X了)
asp.net2.0預設內建了很多HttpModule,從Machine.Config檔案中可以發現以下預設的內建模組:
注2
AnonymouseIdentification --為匿名使用者分配一個臨時身份
FileAuthorization --驗證使用者是否有請求檔案的Windows NT許可
FormsAuthentication --窗體身份驗證模組(如果沒有這個模組,asp.net就無法以使用者名稱/密碼[即FOrms]方式驗證)
OutputCache --輸出快取模組
PassportAuthentication --PassPort驗證模組
Profile --使用者配置模組(如果沒有它,asp.net中就無法使用Profile)
RoleManager --角色管理
SessionSate --會話狀態模組
UrlAuthorization --基於URL的身份驗證模組
WindowsAuthentication --Windows和IIS身份驗證模組
User:
如果您使用過asp.net2.0內建的Membership/Role機制來進行訪問認證,就會對User物件感到很熟悉,比如:
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
//使用者登入過了...
}
我們常用它來判斷當前瀏覽使用者的登入狀態,關於User類的更詳細定義,可參見MSDN
生命週期:
最後再來回顧一下Asp.Net中Page頁的生命週期,Page中定義了幾個事件:
總體上講:一個ASPX頁面被請求時,最終的生命週期就是由Page中定義的上述事件(還有一些可過載的回撥方法)以及以前提到的HttpApplication類中定義的事件(以相應的回撥方法)共同觸發或呼叫,最終疊加形成的一連串處理過程。
如果先不考慮HttpApplication中的事件處理方法(即不考慮我們在Global.ascx.cs中定義的Application_XXX處理方法),Page中的事件(方法)常規觸發(呼叫)順序為:
01.Page_PreInit
02.Page_Init
03.Page_InitComplete
04.Page_PreLoad
05.Page_Load
06.Page_LoadComplete
07.Page_PreRender
08.Page_SaveStateComplete
09.Page_Unload
這是在Page頁面未回發,且不考慮頁面子控制元件的前提下正常的順序,如果加入頁面回發(比如在頁面中放一個asp:Button,然後在Button的Click回發事件中加入處理函式)後,順序稍微有些變化:
01.Page_PreInit
02.Page_Init
03.Page_InitComplete
04.Page_PreLoad
05.Page_Load
06.Button1_Click
07.Page_LoadComplete
08.Page_PreRender
09.Page_SaveStateComplete
10.Page_Unload
不同的地方在於:回發事件Button1_Click在Page_Load後被觸發.
最後再把HttpApplication的事件考慮進來,看下疊加後的順序,不過先彆著急,我們先來看一種特殊情況,如果一個asp.net應用根目錄下未設定預設頁,這時直接瀏覽根目錄,比如http://localhost:2345/ 時,Globl.ascx.cs中定義的Application_XXX方法的呼叫順序如下:
2010-03-28 15:01:39 413 Application_Start
2010-03-28 15:01:39 491 Init
2010-03-28 15:01:39 491 Application_BeginRequest
2010-03-28 15:01:39 506 Application_AuthenticateRequest
2010-03-28 15:01:39 506 Application_PostAuthenticateRequest
2010-03-28 15:01:39 506 Application_AuthorizeRequest
2010-03-28 15:01:39 522 Application_PostAuthorizeRequest
2010-03-28 15:01:39 522 Application_ResolveRequestCache
2010-03-28 15:01:39 522 Application_PostResolveRequestCache
2010-03-28 15:01:39 522 Application_PostMapRequestHandler
2010-03-28 15:01:39 522 Application_AcquireRequestState
2010-03-28 15:01:39 537 Application_PostAcquireRequestState
2010-03-28 15:01:39 537 Application_PreRequestHandlerExecute
2010-03-28 15:01:39 553 Application_Error
2010-03-28 15:01:39 553 Application_EndRequest
2010-03-28 15:01:39 569 Application_PreSendRequestHeaders
2010-03-28 15:01:39 569 Application_PreSendRequestContent
可以看到會觸發Application_Error事件,即HttpRuntime認為這是一個錯誤.
緊接著再瀏覽一個實際存在的頁面,如果這時應用程式有嚴重錯誤,導致Application關閉(比如web.config配置錯誤),呼叫的順序如下:
2010-03-28 15:03:47 704 Application_BeginRequest
2010-03-28 15:03:47 704 Application_AuthenticateRequest
2010-03-28 15:03:47 766 Application_PostAuthenticateRequest
2010-03-28 15:03:47 766 Application_AuthorizeRequest
2010-03-28 15:03:47 766 Application_PostAuthorizeRequest
2010-03-28 15:03:47 766 Application_ResolveRequestCache
2010-03-28 15:03:47 783 Application_PostResolveRequestCache
2010-03-28 15:03:48 667 Application_PostMapRequestHandler
2010-03-28 15:03:48 667 Application_AcquireRequestState
2010-03-28 15:03:48 683 Application_PostAcquireRequestState
2010-03-28 15:03:48 698 Application_PreRequestHandlerExecute
2010-03-28 15:03:48 745 Page_PreInit
2010-03-28 15:04:02 903 Page_Unload
2010-03-28 15:04:02 903 Application_Error
2010-03-28 15:04:02 918 Application_EndRequest
2010-03-28 15:04:02 996 Application_PreSendRequestHeaders
2010-03-28 15:04:02 996 Application_PreSendRequestContent
2010-03-28 15:04:03 371 Application_Disposed
2010-03-28 15:04:03 371 Dispose
2010-03-28 15:04:03 386 Application_End
對比剛才的順序,會發現Application_Start及Init沒有再次被呼叫,也印證了文章前面提到的一些結論(Application_Start在整個asp.net應用生命週期內只觸發一次),而且從最後的三個輸出能知道:應用程式關閉時Application_Disposed,Dispose,Application_End按順序呼叫.
再"重新"瀏覽(指web Server重啟)一下正常訪問的頁面,在不出錯也不回發的情況下,順序如下:
2010-03-28 15:08:11 513 Application_Start
2010-03-28 15:08:11 591 Init
2010-03-28 15:08:11 591 Application_BeginRequest
2010-03-28 15:08:11 591 Application_AuthenticateRequest
2010-03-28 15:08:11 591 Application_PostAuthenticateRequest
2010-03-28 15:08:11 606 Application_AuthorizeRequest
2010-03-28 15:08:11 606 Application_PostAuthorizeRequest
2010-03-28 15:08:11 606 Application_ResolveRequestCache
2010-03-28 15:08:11 606 Application_PostResolveRequestCache
2010-03-28 15:08:11 622 Application_PostMapRequestHandler
2010-03-28 15:08:11 637 Application_EndRequest
2010-03-28 15:08:11 637 Application_PreSendRequestHeaders
2010-03-28 15:08:11 637 Application_PreSendRequestContent
2010-03-28 15:08:11 637 Application_BeginRequest
2010-03-28 15:08:11 637 Application_AuthenticateRequest
2010-03-28 15:08:11 653 Application_PostAuthenticateRequest
2010-03-28 15:08:11 653 Application_AuthorizeRequest
2010-03-28 15:08:11 653 Application_PostAuthorizeRequest
2010-03-28 15:08:11 653 Application_ResolveRequestCache
2010-03-28 15:08:11 653 Application_PostResolveRequestCache
2010-03-28 15:08:11 653 Application_PostMapRequestHandler
2010-03-28 15:08:11 653 Session_Start
2010-03-28 15:08:11 653 Application_AcquireRequestState
2010-03-28 15:08:11 653 Application_PostAcquireRequestState
2010-03-28 15:08:11 653 Application_PreRequestHandlerExecute
2010-03-28 15:08:11 669 Page_PreInit
2010-03-28 15:08:11 684 Page_Init
2010-03-28 15:08:11 684 Page_InitComplete
2010-03-28 15:08:11 684 Page_PreLoad
2010-03-28 15:08:11 684 Page_Load
2010-03-28 15:08:11 684 Page_LoadComplete
2010-03-28 15:08:11 684 Page_PreRender
2010-03-28 15:08:11 684 Page_SaveStateComplete
2010-03-28 15:08:11 700 Page_Unload
2010-03-28 15:08:11 700 Application_PostRequestHandlerExecute
2010-03-28 15:08:11 700 Application_ReleaseRequestState
2010-03-28 15:08:11 700 Application_PostReleaseRequestState
2010-03-28 15:08:11 700 Application_UpdateRequestCache
2010-03-28 15:08:11 700 Application_PostUpdateRequestCache
2010-03-28 15:08:11 700 Application_EndRequest
2010-03-28 15:08:11 700 Application_PreSendRequestHeaders
2010-03-28 15:08:11 700 Application_PreSendRequestContent
2010-03-28 15:08:11 793 Application_BeginRequest
2010-03-28 15:08:11 793 Application_AuthenticateRequest
2010-03-28 15:08:11 793 Application_PostAuthenticateRequest
2010-03-28 15:08:11 793 Application_AuthorizeRequest
2010-03-28 15:08:11 793 Application_PostAuthorizeRequest
2010-03-28 15:08:11 793 Application_ResolveRequestCache
2010-03-28 15:08:11 793 Application_PostResolveRequestCache
2010-03-28 15:08:11 809 Application_PostMapRequestHandler
2010-03-28 15:08:11 809 Application_AcquireRequestState
2010-03-28 15:08:11 809 Application_PostAcquireRequestState
2010-03-28 15:08:11 809 Application_PreRequestHandlerExecute
2010-03-28 15:08:11 825 Application_PostRequestHandlerExecute
2010-03-28 15:08:11 825 Application_ReleaseRequestState
2010-03-28 15:08:11 840 Application_PostReleaseRequestState
2010-03-28 15:08:11 949 Application_UpdateRequestCache
2010-03-28 15:08:11 949 Application_PostUpdateRequestCache
2010-03-28 15:08:11 965 Application_EndRequest
2010-03-28 15:08:11 981 Application_PreSendRequestHeaders
2010-03-28 15:08:11 981 Application_PreSendRequestContent
哇!原來一個頁面訪問下來,會呼叫到這麼多的方法,怪不得很多高併發的大型網站,通常都要自己寫一個精減的HttpHandler用來取代Page做為基類,以期望獲得更好的效能
最後:我們在做網站開發時,不可能只用到Page頁,很多時候還會用到UserControl(使用者自定義控制元件),先看下它的繼承關係,比如我們建立了一個TestUserControl的使用者控制元件
TestUserControl --> UserControl ---> TemplateControl --> Control
最終在Control類的定義下,可以看到
這似乎表明使用者控制元件中,應該有Page_Init,Page_Load,Page_Unload...等事件,通常我們只用到Init,Load事件,如果加入一個使用者控制元件後,整個生命週期就更復雜了:
2010-06-12 15:35:28 042 Application_Start
2010-06-12 15:35:28 072 Init
2010-06-12 15:35:28 072 Application_BeginRequest
2010-06-12 15:35:28 082 Application_AuthenticateRequest
2010-06-12 15:35:28 082 Application_PostAuthenticateRequest
2010-06-12 15:35:28 092 Application_AuthorizeRequest
2010-06-12 15:35:28 102 Application_PostAuthorizeRequest
2010-06-12 15:35:28 102 Application_ResolveRequestCache
2010-06-12 15:35:28 112 Application_PostResolveRequestCache
2010-06-12 15:35:28 122 Application_PostMapRequestHandler
2010-06-12 15:35:28 142 Application_EndRequest
2010-06-12 15:35:28 142 Application_PreSendRequestHeaders
2010-06-12 15:35:28 142 Application_PreSendRequestContent
2010-06-12 15:35:28 152 Application_BeginRequest
2010-06-12 15:35:28 152 Application_AuthenticateRequest
2010-06-12 15:35:28 162 Application_PostAuthenticateRequest
2010-06-12 15:35:28 162 Application_AuthorizeRequest
2010-06-12 15:35:28 162 Application_PostAuthorizeRequest
2010-06-12 15:35:28 172 Application_ResolveRequestCache
2010-06-12 15:35:28 172 Application_PostResolveRequestCache
2010-06-12 15:35:28 172 Application_PostMapRequestHandler
2010-06-12 15:35:28 172 Session_Start
2010-06-12 15:35:28 172 Application_AcquireRequestState
2010-06-12 15:35:28 182 Application_PostAcquireRequestState
2010-06-12 15:35:28 182 Application_PreRequestHandlerExecute
2010-06-12 15:35:28 192 Page_PreInit
2010-06-12 15:35:28 192 TestUserControl.Page_Init
2010-06-12 15:35:28 202 Page_Init
2010-06-12 15:35:28 202 TestUserControl.TestProperty.Set
2010-06-12 15:35:28 202 Page_InitComplete
2010-06-12 15:35:28 202 Page_PreLoad
2010-06-12 15:35:28 202 Page_Load
2010-06-12 15:35:28 202 TestUserControl.Page_Load
2010-06-12 15:35:28 202 TestUserControl.ShowData()
2010-06-12 15:35:28 212 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 212 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 212 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 212 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 212 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 222 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 222 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 222 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 222 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 222 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 232 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 232 Page_LoadComplete
2010-06-12 15:35:28 232 Page_PreRender
2010-06-12 15:35:28 232 TestUserControl.Page_PreRender
2010-06-12 15:35:28 242 Page_SaveStateComplete
2010-06-12 15:35:28 242 TestUserControl.Page_Unload
2010-06-12 15:35:28 252 Page_Unload
2010-06-12 15:35:28 252 Application_PostRequestHandlerExecute
2010-06-12 15:35:28 252 Application_ReleaseRequestState
2010-06-12 15:35:28 252 Application_PostReleaseRequestState
2010-06-12 15:35:28 262 Application_UpdateRequestCache
2010-06-12 15:35:28 262 Application_PostUpdateRequestCache
2010-06-12 15:35:28 262 Application_EndRequest
2010-06-12 15:35:28 272 Application_PreSendRequestHeaders
2010-06-12 15:35:28 272 Application_PreSendRequestContent
2010-06-12 15:35:28 282 Application_BeginRequest
2010-06-12 15:35:28 292 Application_AuthenticateRequest
2010-06-12 15:35:28 292 Application_PostAuthenticateRequest
2010-06-12 15:35:28 302 Application_AuthorizeRequest
2010-06-12 15:35:28 302 Application_PostAuthorizeRequest
2010-06-12 15:35:28 302 Application_ResolveRequestCache
2010-06-12 15:35:28 312 Application_PostResolveRequestCache
2010-06-12 15:35:28 312 Application_PostMapRequestHandler
2010-06-12 15:35:28 322 Application_AcquireRequestState
2010-06-12 15:35:28 322 Application_PostAcquireRequestState
2010-06-12 15:35:28 322 Application_PreRequestHandlerExecute
2010-06-12 15:35:28 332 Application_PostRequestHandlerExecute
2010-06-12 15:35:28 332 Application_ReleaseRequestState
2010-06-12 15:35:28 332 Application_PostReleaseRequestState
2010-06-12 15:35:28 342 Application_UpdateRequestCache
2010-06-12 15:35:28 342 Application_PostUpdateRequestCache
2010-06-12 15:35:28 342 Application_EndRequest
2010-06-12 15:35:28 342 Application_PreSendRequestHeaders
2010-06-12 15:35:28 342 Application_PreSendRequestContent
2010-06-12 15:36:40 034 Session_End
注1
Application -->相當於傳統意義上asp時代的application物件,通常用於定義一個asp.net應用的全域性變數
Context -->HttpContext(上下文)類的例項【Asp.Net新增的】
Modules -->影響當前應用程式的HttpModule模組集合
Request -->類似於asp中的Request物件,通常用於接收一些特定的值(比如Request.Form或Request.QueryString)
Response -->類似於asp中的Response物件,通常用於向做頁面輸出指定內容(比如Resonse.Write)
Server -->類似於asp中的Server物件,通過它能獲得一些服務端的資訊(比如Server.MapPath)
Session -->類似於asp中的Session物件
User -->用於獲取使用者認證相關的安全資訊
從上面的屬性可以發現:很多其實在asp年代已在使用,只有Context,Modules,User這三個是Asp.Net新增的
HttpApplication類除了具備"注1"的幾個屬性外,還有自己的方法,這裡特別提一下Init方法和Dispose方法,這二個方法均可過載.
它們的呼叫時機為:
Init方法在Application_Start之後呼叫,而Dispose在Application_End之前呼叫,另外Application_Start在整個asp.net應用的生命週期內只激發一次(比如IIS啟動或網站啟動時),類似的Application_End也只有當asp.net應用程式關閉時被呼叫(比如IIS停止或網站停止時)
除了Application_Start和Application_End方法,HttpApplication還提供了以下事件:
這些事件包括前面提到的可過載的Init及Dispose方法,再加上Session對應的Session_Start與Session_End方法,均可直接在Global.ascx.cs中以Application_XXX的形式使用(因為Global.ascx.cs中定義的類Global本身就是繼承自HttpApplication的)
public class Global : System.Web.HttpApplication
再來看一下相對asp而言,新增的Context,Modules,User這三個屬性
Context:
Context即HttpContext類的例項,在幾乎整個aspx頁面生命週期中,Context上下文一直伴隨著各個環節向下傳遞
所以我們幾乎可以在web應用中的任何環節,用HttpContext.Current來引用到當前的上下文例項,從HttpContext的定義上,還可以發現Context本身的屬性中,又可以得到Application,ApplicationInstance,Profile,Response.Request...等物件的例項引用
回想一下:
public class Handler1 : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Write("Hello World");
}
public bool IsReusable
{
get
{
return false;
}
}
}
我們在使用一個ashx檔案時,ProcessRequest方法便是把當前上下文傳遞進來,進而通過context得到Response物件的引用,最終可以向頁面輸出任何想要的內容.
Modules:
每一個實現了IHttpModule介面的類,就可以被認為是Http模組元件,可以理解為http請求攔截器,攔截到http請求後,它能修改正在被處理的Context上下文,完事兒之後,再把控制權交還給管道,如果還有其它模組,則依次繼續處理,直到所有Modules集合中的HttpModule都“爽”完為止(注:可憐的http請求就這樣給各個httpModule輪X了)
asp.net2.0預設內建了很多HttpModule,從Machine.Config檔案中可以發現以下預設的內建模組:
注2
AnonymouseIdentification --為匿名使用者分配一個臨時身份
FileAuthorization --驗證使用者是否有請求檔案的Windows NT許可
FormsAuthentication --窗體身份驗證模組(如果沒有這個模組,asp.net就無法以使用者名稱/密碼[即FOrms]方式驗證)
OutputCache --輸出快取模組
PassportAuthentication --PassPort驗證模組
Profile --使用者配置模組(如果沒有它,asp.net中就無法使用Profile)
RoleManager --角色管理
SessionSate --會話狀態模組
UrlAuthorization --基於URL的身份驗證模組
WindowsAuthentication --Windows和IIS身份驗證模組
User:
如果您使用過asp.net2.0內建的Membership/Role機制來進行訪問認證,就會對User物件感到很熟悉,比如:
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
//使用者登入過了...
}
我們常用它來判斷當前瀏覽使用者的登入狀態,關於User類的更詳細定義,可參見MSDN
生命週期:
最後再來回顧一下Asp.Net中Page頁的生命週期,Page中定義了幾個事件:
總體上講:一個ASPX頁面被請求時,最終的生命週期就是由Page中定義的上述事件(還有一些可過載的回撥方法)以及以前提到的HttpApplication類中定義的事件(以相應的回撥方法)共同觸發或呼叫,最終疊加形成的一連串處理過程。
如果先不考慮HttpApplication中的事件處理方法(即不考慮我們在Global.ascx.cs中定義的Application_XXX處理方法),Page中的事件(方法)常規觸發(呼叫)順序為:
01.Page_PreInit
02.Page_Init
03.Page_InitComplete
04.Page_PreLoad
05.Page_Load
06.Page_LoadComplete
07.Page_PreRender
08.Page_SaveStateComplete
09.Page_Unload
這是在Page頁面未回發,且不考慮頁面子控制元件的前提下正常的順序,如果加入頁面回發(比如在頁面中放一個asp:Button,然後在Button的Click回發事件中加入處理函式)後,順序稍微有些變化:
01.Page_PreInit
02.Page_Init
03.Page_InitComplete
04.Page_PreLoad
05.Page_Load
06.Button1_Click
07.Page_LoadComplete
08.Page_PreRender
09.Page_SaveStateComplete
10.Page_Unload
不同的地方在於:回發事件Button1_Click在Page_Load後被觸發.
最後再把HttpApplication的事件考慮進來,看下疊加後的順序,不過先彆著急,我們先來看一種特殊情況,如果一個asp.net應用根目錄下未設定預設頁,這時直接瀏覽根目錄,比如http://localhost:2345/ 時,Globl.ascx.cs中定義的Application_XXX方法的呼叫順序如下:
2010-03-28 15:01:39 413 Application_Start
2010-03-28 15:01:39 491 Init
2010-03-28 15:01:39 491 Application_BeginRequest
2010-03-28 15:01:39 506 Application_AuthenticateRequest
2010-03-28 15:01:39 506 Application_PostAuthenticateRequest
2010-03-28 15:01:39 506 Application_AuthorizeRequest
2010-03-28 15:01:39 522 Application_PostAuthorizeRequest
2010-03-28 15:01:39 522 Application_ResolveRequestCache
2010-03-28 15:01:39 522 Application_PostResolveRequestCache
2010-03-28 15:01:39 522 Application_PostMapRequestHandler
2010-03-28 15:01:39 522 Application_AcquireRequestState
2010-03-28 15:01:39 537 Application_PostAcquireRequestState
2010-03-28 15:01:39 537 Application_PreRequestHandlerExecute
2010-03-28 15:01:39 553 Application_Error
2010-03-28 15:01:39 553 Application_EndRequest
2010-03-28 15:01:39 569 Application_PreSendRequestHeaders
2010-03-28 15:01:39 569 Application_PreSendRequestContent
可以看到會觸發Application_Error事件,即HttpRuntime認為這是一個錯誤.
緊接著再瀏覽一個實際存在的頁面,如果這時應用程式有嚴重錯誤,導致Application關閉(比如web.config配置錯誤),呼叫的順序如下:
2010-03-28 15:03:47 704 Application_BeginRequest
2010-03-28 15:03:47 704 Application_AuthenticateRequest
2010-03-28 15:03:47 766 Application_PostAuthenticateRequest
2010-03-28 15:03:47 766 Application_AuthorizeRequest
2010-03-28 15:03:47 766 Application_PostAuthorizeRequest
2010-03-28 15:03:47 766 Application_ResolveRequestCache
2010-03-28 15:03:47 783 Application_PostResolveRequestCache
2010-03-28 15:03:48 667 Application_PostMapRequestHandler
2010-03-28 15:03:48 667 Application_AcquireRequestState
2010-03-28 15:03:48 683 Application_PostAcquireRequestState
2010-03-28 15:03:48 698 Application_PreRequestHandlerExecute
2010-03-28 15:03:48 745 Page_PreInit
2010-03-28 15:04:02 903 Page_Unload
2010-03-28 15:04:02 903 Application_Error
2010-03-28 15:04:02 918 Application_EndRequest
2010-03-28 15:04:02 996 Application_PreSendRequestHeaders
2010-03-28 15:04:02 996 Application_PreSendRequestContent
2010-03-28 15:04:03 371 Application_Disposed
2010-03-28 15:04:03 371 Dispose
2010-03-28 15:04:03 386 Application_End
對比剛才的順序,會發現Application_Start及Init沒有再次被呼叫,也印證了文章前面提到的一些結論(Application_Start在整個asp.net應用生命週期內只觸發一次),而且從最後的三個輸出能知道:應用程式關閉時Application_Disposed,Dispose,Application_End按順序呼叫.
再"重新"瀏覽(指web Server重啟)一下正常訪問的頁面,在不出錯也不回發的情況下,順序如下:
2010-03-28 15:08:11 513 Application_Start
2010-03-28 15:08:11 591 Init
2010-03-28 15:08:11 591 Application_BeginRequest
2010-03-28 15:08:11 591 Application_AuthenticateRequest
2010-03-28 15:08:11 591 Application_PostAuthenticateRequest
2010-03-28 15:08:11 606 Application_AuthorizeRequest
2010-03-28 15:08:11 606 Application_PostAuthorizeRequest
2010-03-28 15:08:11 606 Application_ResolveRequestCache
2010-03-28 15:08:11 606 Application_PostResolveRequestCache
2010-03-28 15:08:11 622 Application_PostMapRequestHandler
2010-03-28 15:08:11 637 Application_EndRequest
2010-03-28 15:08:11 637 Application_PreSendRequestHeaders
2010-03-28 15:08:11 637 Application_PreSendRequestContent
2010-03-28 15:08:11 637 Application_BeginRequest
2010-03-28 15:08:11 637 Application_AuthenticateRequest
2010-03-28 15:08:11 653 Application_PostAuthenticateRequest
2010-03-28 15:08:11 653 Application_AuthorizeRequest
2010-03-28 15:08:11 653 Application_PostAuthorizeRequest
2010-03-28 15:08:11 653 Application_ResolveRequestCache
2010-03-28 15:08:11 653 Application_PostResolveRequestCache
2010-03-28 15:08:11 653 Application_PostMapRequestHandler
2010-03-28 15:08:11 653 Session_Start
2010-03-28 15:08:11 653 Application_AcquireRequestState
2010-03-28 15:08:11 653 Application_PostAcquireRequestState
2010-03-28 15:08:11 653 Application_PreRequestHandlerExecute
2010-03-28 15:08:11 669 Page_PreInit
2010-03-28 15:08:11 684 Page_Init
2010-03-28 15:08:11 684 Page_InitComplete
2010-03-28 15:08:11 684 Page_PreLoad
2010-03-28 15:08:11 684 Page_Load
2010-03-28 15:08:11 684 Page_LoadComplete
2010-03-28 15:08:11 684 Page_PreRender
2010-03-28 15:08:11 684 Page_SaveStateComplete
2010-03-28 15:08:11 700 Page_Unload
2010-03-28 15:08:11 700 Application_PostRequestHandlerExecute
2010-03-28 15:08:11 700 Application_ReleaseRequestState
2010-03-28 15:08:11 700 Application_PostReleaseRequestState
2010-03-28 15:08:11 700 Application_UpdateRequestCache
2010-03-28 15:08:11 700 Application_PostUpdateRequestCache
2010-03-28 15:08:11 700 Application_EndRequest
2010-03-28 15:08:11 700 Application_PreSendRequestHeaders
2010-03-28 15:08:11 700 Application_PreSendRequestContent
2010-03-28 15:08:11 793 Application_BeginRequest
2010-03-28 15:08:11 793 Application_AuthenticateRequest
2010-03-28 15:08:11 793 Application_PostAuthenticateRequest
2010-03-28 15:08:11 793 Application_AuthorizeRequest
2010-03-28 15:08:11 793 Application_PostAuthorizeRequest
2010-03-28 15:08:11 793 Application_ResolveRequestCache
2010-03-28 15:08:11 793 Application_PostResolveRequestCache
2010-03-28 15:08:11 809 Application_PostMapRequestHandler
2010-03-28 15:08:11 809 Application_AcquireRequestState
2010-03-28 15:08:11 809 Application_PostAcquireRequestState
2010-03-28 15:08:11 809 Application_PreRequestHandlerExecute
2010-03-28 15:08:11 825 Application_PostRequestHandlerExecute
2010-03-28 15:08:11 825 Application_ReleaseRequestState
2010-03-28 15:08:11 840 Application_PostReleaseRequestState
2010-03-28 15:08:11 949 Application_UpdateRequestCache
2010-03-28 15:08:11 949 Application_PostUpdateRequestCache
2010-03-28 15:08:11 965 Application_EndRequest
2010-03-28 15:08:11 981 Application_PreSendRequestHeaders
2010-03-28 15:08:11 981 Application_PreSendRequestContent
哇!原來一個頁面訪問下來,會呼叫到這麼多的方法,怪不得很多高併發的大型網站,通常都要自己寫一個精減的HttpHandler用來取代Page做為基類,以期望獲得更好的效能
最後:我們在做網站開發時,不可能只用到Page頁,很多時候還會用到UserControl(使用者自定義控制元件),先看下它的繼承關係,比如我們建立了一個TestUserControl的使用者控制元件
TestUserControl --> UserControl ---> TemplateControl --> Control
最終在Control類的定義下,可以看到
這似乎表明使用者控制元件中,應該有Page_Init,Page_Load,Page_Unload...等事件,通常我們只用到Init,Load事件,如果加入一個使用者控制元件後,整個生命週期就更復雜了:
2010-06-12 15:35:28 042 Application_Start
2010-06-12 15:35:28 072 Init
2010-06-12 15:35:28 072 Application_BeginRequest
2010-06-12 15:35:28 082 Application_AuthenticateRequest
2010-06-12 15:35:28 082 Application_PostAuthenticateRequest
2010-06-12 15:35:28 092 Application_AuthorizeRequest
2010-06-12 15:35:28 102 Application_PostAuthorizeRequest
2010-06-12 15:35:28 102 Application_ResolveRequestCache
2010-06-12 15:35:28 112 Application_PostResolveRequestCache
2010-06-12 15:35:28 122 Application_PostMapRequestHandler
2010-06-12 15:35:28 142 Application_EndRequest
2010-06-12 15:35:28 142 Application_PreSendRequestHeaders
2010-06-12 15:35:28 142 Application_PreSendRequestContent
2010-06-12 15:35:28 152 Application_BeginRequest
2010-06-12 15:35:28 152 Application_AuthenticateRequest
2010-06-12 15:35:28 162 Application_PostAuthenticateRequest
2010-06-12 15:35:28 162 Application_AuthorizeRequest
2010-06-12 15:35:28 162 Application_PostAuthorizeRequest
2010-06-12 15:35:28 172 Application_ResolveRequestCache
2010-06-12 15:35:28 172 Application_PostResolveRequestCache
2010-06-12 15:35:28 172 Application_PostMapRequestHandler
2010-06-12 15:35:28 172 Session_Start
2010-06-12 15:35:28 172 Application_AcquireRequestState
2010-06-12 15:35:28 182 Application_PostAcquireRequestState
2010-06-12 15:35:28 182 Application_PreRequestHandlerExecute
2010-06-12 15:35:28 192 Page_PreInit
2010-06-12 15:35:28 192 TestUserControl.Page_Init
2010-06-12 15:35:28 202 Page_Init
2010-06-12 15:35:28 202 TestUserControl.TestProperty.Set
2010-06-12 15:35:28 202 Page_InitComplete
2010-06-12 15:35:28 202 Page_PreLoad
2010-06-12 15:35:28 202 Page_Load
2010-06-12 15:35:28 202 TestUserControl.Page_Load
2010-06-12 15:35:28 202 TestUserControl.ShowData()
2010-06-12 15:35:28 212 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 212 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 212 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 212 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 212 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 222 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 222 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 222 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 222 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 222 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 232 TestUserControl.Repeater1.ItemDataBound()
2010-06-12 15:35:28 232 Page_LoadComplete
2010-06-12 15:35:28 232 Page_PreRender
2010-06-12 15:35:28 232 TestUserControl.Page_PreRender
2010-06-12 15:35:28 242 Page_SaveStateComplete
2010-06-12 15:35:28 242 TestUserControl.Page_Unload
2010-06-12 15:35:28 252 Page_Unload
2010-06-12 15:35:28 252 Application_PostRequestHandlerExecute
2010-06-12 15:35:28 252 Application_ReleaseRequestState
2010-06-12 15:35:28 252 Application_PostReleaseRequestState
2010-06-12 15:35:28 262 Application_UpdateRequestCache
2010-06-12 15:35:28 262 Application_PostUpdateRequestCache
2010-06-12 15:35:28 262 Application_EndRequest
2010-06-12 15:35:28 272 Application_PreSendRequestHeaders
2010-06-12 15:35:28 272 Application_PreSendRequestContent
2010-06-12 15:35:28 282 Application_BeginRequest
2010-06-12 15:35:28 292 Application_AuthenticateRequest
2010-06-12 15:35:28 292 Application_PostAuthenticateRequest
2010-06-12 15:35:28 302 Application_AuthorizeRequest
2010-06-12 15:35:28 302 Application_PostAuthorizeRequest
2010-06-12 15:35:28 302 Application_ResolveRequestCache
2010-06-12 15:35:28 312 Application_PostResolveRequestCache
2010-06-12 15:35:28 312 Application_PostMapRequestHandler
2010-06-12 15:35:28 322 Application_AcquireRequestState
2010-06-12 15:35:28 322 Application_PostAcquireRequestState
2010-06-12 15:35:28 322 Application_PreRequestHandlerExecute
2010-06-12 15:35:28 332 Application_PostRequestHandlerExecute
2010-06-12 15:35:28 332 Application_ReleaseRequestState
2010-06-12 15:35:28 332 Application_PostReleaseRequestState
2010-06-12 15:35:28 342 Application_UpdateRequestCache
2010-06-12 15:35:28 342 Application_PostUpdateRequestCache
2010-06-12 15:35:28 342 Application_EndRequest
2010-06-12 15:35:28 342 Application_PreSendRequestHeaders
2010-06-12 15:35:28 342 Application_PreSendRequestContent
2010-06-12 15:36:40 034 Session_End
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/25897606/viewspace-757293/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- asp.net 頁面 生命週期ASP.NET
- ASP.NET頁面生命週期與應用程式生命週期ASP.NET
- Asp.Net頁面生命週期(二)ASP.NET
- ASP.NET三劍客 HttpApplication HttpModule HttpHandler 解析ASP.NETHTTPAPP
- asp.net常規頁生命週期階段列表和事件列表ASP.NET事件
- Vue例項及生命週期Vue
- Activity簡介及生命週期
- 【UniApp】-uni-app-OptionAPI應用生命週期和頁面生命週期APPAPI
- C# 11頁面生命週期C#
- 微信小程式頁面的生命週期微信小程式
- 記憶體頁生命週期下降記憶體
- 鴻蒙Navigation頁面生命週期鴻蒙Navigation
- asp.net core服務的生命週期ASP.NET
- 【UniApp】-uni-app-CompositionAPI應用生命週期和頁面生命週期APPAPI
- 生命週期
- 2、ASP.NET Core中服務的生命週期ASP.NET
- Maven生命週期及常用命令Maven
- View生命週期與Activity生命週期的關係View
- PHP 生命週期PHP
- Flutter - 生命週期Flutter
- sessionStorag 生命週期Session
- Fragment生命週期Fragment
- Activity生命週期
- vue - 生命週期Vue
- React生命週期React
- ubuntu生命週期Ubuntu
- React 生命週期React
- vue生命週期Vue
- Salesforce 生命週期管理(一)應用生命週期淺談Salesforce
- React元件的狀態及生命週期事件React元件事件
- 為ElementUI的標籤頁新增生命週期UI
- ArkTS 頁面和自定義元件生命週期元件
- ASP.NET 伺服器控制元件的生命週期ASP.NET伺服器控制元件
- 【Michael Xu】ASP.NET AJAX 客戶端生命週期事件ASP.NET客戶端事件
- Activity生命週期onDestroy
- Flutter -- Element生命週期Flutter
- Flutter 的生命週期Flutter
- SQL的生命週期SQL