ASP.Net頁面生命周期與Page_Load方法的工作原理介紹
一、ASP.Net Web應用程序中的請求處理過程
二、 http模塊生命周期:
三、Asp.NET頁面生命周期
1、階段
階段 | 說明 |
請求頁面(Page Request) | 嚴格地說,這個階段不是頁面生命周期的一部分。而是頁面生命周期之前的一個階段。Asp.NET接收到一個頁面請求之后,執(zhí)行分析和編譯頁面的工作或者從緩存中取出該頁面發(fā)送給客戶端。 |
開始(Start) | 在這個階段,Asp.NET設(shè)置Page對象的Request和Response屬性;確定該頁面請求是否為PostBack;給頁面設(shè)置UICulture屬性。 |
初始化(Initialization) | 頁面和控件對象的初始化;為控件設(shè)置UniqueID;為頁面設(shè)置Master Page和Theme;需要特別注意的是,在這個階段,客戶端提交的數(shù)據(jù),還沒有被恢復到頁面控件中去,包括ViewState在內(nèi)。 |
加載(Load) | 加載ViewState; 將表單數(shù)據(jù)設(shè)置到對應控件中去。 |
回發(fā)事件(PostBack event) | 如果當前請求是一個PostBack請求,那么必然有某個事情導致了這次PostBack, 現(xiàn)在就到了執(zhí)行該事件在服務器上的Event Handler的時候了。 這個階段主要的問題在于Validation和Event Handler的執(zhí)行次序。 1.如果該Event本身沒有直接導致Validation, 比如我在Button上設(shè)置了不需要Validation,那么該Button的Click Event Handler先執(zhí)行,然后頁面上會執(zhí)行頁面上所有Validator 控件的Validator方法,然后設(shè)置頁面的IsValid屬性。 2.如果該Event本身直接導致了Validation,比如用戶點擊了一個Button,這個Button默認就會導致Validator被調(diào)用。這時候,Validation的執(zhí)行是在Button的Click Event Handler之前的。等你進入Button的Click Event Handler的時候,頁面的IsValid屬性已經(jīng)設(shè)置好了。 |
渲染(Rendering) | Asp.NET將頁面和所有控件的ViewState保存到Form表單中去。然后調(diào)用所有控件和頁面的Render方法來輸出Html. |
卸載(Unload) | 執(zhí)行到這個階段的時候,頁面已經(jīng)將Html輸出到客戶端了。這個階段要做的事情就包括:卸載Request對象和Response對象,執(zhí)行一些清理工作。 |
下面將頁面生命周期與服務器控件生命周期在一張圖上(從MSDN中復制)綜合展示:
2、頁面中事件/階段的執(zhí)行模式:
事件&方法 | Page ONLY | Control ONLY | 頂層到底層 | 頂層到頂層 |
---|---|---|---|---|
PreInit | YES | —— | ||
Init | 事件 | YES | ||
InitComplete | YES | —— | ||
LoadViewState | 方法 | YES | ||
ProcessPostData | 方法 | YES | ||
PreLoad | YES | —— | ||
Load | 事件 | YES | ||
PostBack Event | YES | —— | ||
LoadComplete | YES | —— | ||
PreRender | 事件 | YES | ||
DataBinding Event | YES | —— | ||
PreRenderComplete | YES | —— | ||
SaveViewState | 方法 | YES | ||
SaveStateComplete | YES | —— | ||
Render | 方法 | YES | ||
Unload | 事件 | YES |
3、示例程序
public partial class _Default : System.Web.UI.Page { protected int i = 1; protected void Page_PreInit(object sender, EventArgs e) { Response.Write(i + ".PreInit:當頁面初始化開始時發(fā)生"); i++; Response.Write(""); } protected void Page_Init(object sender, EventArgs e) { Response.Write(i + ".Init:當服務器空間初始化時發(fā)生"); i++; Response.Write(""); } protected void Page_InitComplete(object sender, EventArgs e) { Response.Write(i + ".InitComplete:當頁初始化完成時發(fā)生"); i++; Response.Write(""); } protected void Page_PreLoad(object sender, EventArgs e) { Response.Write(i + ".PreLoad:當頁load事件前發(fā)生"); i++; Response.Write(""); } protected void Page_Load(object sender, EventArgs e) { Response.Write(i + ".Load:當服務器控件加載到Page對象中時發(fā)生(加載頁面時)"); i++; Response.Write(""); //在Load和LoadComplete之間會執(zhí)行控件事件. //如 Button 控件的 Click 事件或 TextBox 控件的 TextChanged 事件。 } protected void Page_LoadComplete(object sender, EventArgs e) { Response.Write(i + ".LoadComplete:當頁面生命周期的加載階段結(jié)束時發(fā)生"); i++; Response.Write(""); } protected void Page_PreRender(object sender, EventArgs e) { Response.Write(i + ".PreRender:當頁加載控件之后,呈現(xiàn)之前發(fā)生,使用該事件對頁或其控件的內(nèi)容進行最后更改(預呈現(xiàn))"); i++; Response.Write(""); } protected void Page_PreRenderComplete(object sender, EventArgs e) { Response.Write(i + ".PreRenderComplete:呈現(xiàn)內(nèi)容前發(fā)生.(預呈現(xiàn)完成)"); i++; Response.Write(""); } protected void Page_SaveStateComplete(object sender, EventArgs e) { /*網(wǎng)頁上控件的狀態(tài)信息是在 PreRenderComplete 事件后保存的。 在SaveStateComplete事件之前用Trace查看頁時其實在該事件前還有 一個SaveState事件,只是這里無法演示. 注意:SaveStateComplete 事件在將頁和頁上控件的視圖狀態(tài)和控件狀態(tài)保存到持久性介質(zhì)之后引發(fā)。 這是在頁被呈現(xiàn)到請求瀏覽器之前引發(fā)的最后一個事件。*/ Response.Write(i + ".SaveStateComplete:在頁已完成對頁和頁上控件的所有視圖狀態(tài)和控件狀態(tài)信息的保存后發(fā)生."); i++; Response.Write(""); /*最后一部操作 呈現(xiàn):Render: 它不是事件;在處理的這個階段,Page 對象會在每個控件上調(diào)用此方法Render()。 所有 ASP.NET Web 服務器控件都有一個用于寫出發(fā)送給瀏覽器的控件標記的 Render 方法。*/ /*當你關(guān)閉頁面的時候就會引發(fā)UnLoad(當服務器控件從內(nèi)存中卸載時發(fā)生) 和Disposed兩事件(當從內(nèi)存釋放服務器控件時發(fā)生,這是服務器控件生存期的最后階段) 首先加載UnLoad事件:卸載頁面:完全呈現(xiàn)頁、將頁發(fā)送至客戶端并準備丟棄時, 將調(diào)用卸載。此時,將卸載頁屬性(如Response和Request)并執(zhí)行清理. 最后加載Disposed事件,釋放資源,生命周期結(jié)束.... */ } }
結(jié)果顯示:
四、PageLoad 與 OnLoad區(qū)別:
1、用VS.Net生成的頁面中的Page_Load方法(事件處理程序)就是響應Page.Load事件的。對于每一次請求,Load事件都會觸發(fā),Page_Load方法就會執(zhí)行。
2、@Page指令中的AutoEventWireup=true時,頁面會與某些特殊的事件方法綁定,自動識別這些具有特定名稱的事件。這些特定名稱包括:Page_Init, Page_Load, Page_DataBind, Page_PreRender和Page_Unload等。asp.net不需要顯示的來綁定事件處理程序,它會在運行時自動的根據(jù)他們的方法名和簽名綁定事件,對每一個事件,ASP.NET會根據(jù)Page_eventname這種模式去搜尋方法,如果沒有找到帶此簽名的事件處理程序,則 ASP.NET 將檢查沒有參數(shù)的重載。
當時AutoEventWireup=false的時候,則必須顯示綁定事件方法,比如,你有一個Page_Load方法,只有當你這樣寫代碼的時候,才會觸發(fā)事件方法:Page.Load += Page_Load;在這種情況下,方法名稱不必遵循某一模式。
3、Page.Load事件是在System.Web.UI.Control類中定義的(此類是Page和所有服務器控件的基類),是在OnLoad方法中觸發(fā)Page.Load事件。
因此如果在Page頁面里重寫了OnLoad方法,則此時雖然是用的AutoEventWireup=true,但Page_Load方法也不會被執(zhí)行。如果比較考慮性能,建議用override Oneventname方法的方式來實現(xiàn)頁面的事件加載。
public partial class Default : Page { protected void Page_Load(object sender, EventArgs e) { Response.Write("2"); } protected override void OnLoad(EventArgs e) { Response.Write("1"); base.OnLoad(e); Response.Write("3"); } }
輸出123。首先由于override父類的OnLoad,所以先執(zhí)行頁面的OnLoad方法,輸出1,然后執(zhí)行父類的OnLoad方法,一直上推到執(zhí)行完Control類的OnLoad方法后,執(zhí)行Load事件的委托鏈方法,執(zhí)行Page_Load方法,輸出2。最后回到
頁面的OnLoad方法輸出3。如果AutoEventWireup=false,則Page_Load不執(zhí)行。
五、總結(jié)
三張圖片詳解Asp.Net 全生命周期
1、第一張圖片從全局說明從客戶端發(fā)出一個Request請求,服務器windows內(nèi)核中的HTTP.SYS組件接收該請求開始到IIS處理完該請求并響應到客戶端結(jié)束。
2、第二張圖片為圖1中Http處理管線的詳細步驟
3、 第三張圖片為圖2Http處理管線中調(diào)用處理程序(HttpHandler, 此處為Page對象)的詳細生命周期過程。
到此這篇關(guān)于ASP.Net頁面生命周期與Page_Load方法的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
使用vs2022在.net6中調(diào)試帶typescript的靜態(tài)頁面
這篇文章介紹了使用vs2022在.net6中調(diào)試帶typescript的靜態(tài)頁面,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-12-12WPF框架Prism中ViewModelLocator用法介紹
這篇文章介紹了WPF框架Prism中ViewModelLocator的用法,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-02-02IIS部署ASP.NET?Core項目及常見問題總結(jié)
這篇文章介紹了IIS部署ASP.NET?Core項目的方法及常見問題總結(jié),對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-01-01