ASP.Net頁面生命周期與Page_Load方法的工作原理介紹
一、ASP.Net Web應(yīng)用程序中的請求處理過程

二、 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ù),還沒有被恢復(fù)到頁面控件中去,包括ViewState在內(nèi)。 |
| 加載(Load) | 加載ViewState; 將表單數(shù)據(jù)設(shè)置到對應(yīng)控件中去。 |
| 回發(fā)事件(PostBack event) | 如果當前請求是一個PostBack請求,那么必然有某個事情導(dǎo)致了這次PostBack, 現(xiàn)在就到了執(zhí)行該事件在服務(wù)器上的Event Handler的時候了。 這個階段主要的問題在于Validation和Event Handler的執(zhí)行次序。 1.如果該Event本身沒有直接導(dǎo)致Validation, 比如我在Button上設(shè)置了不需要Validation,那么該Button的Click Event Handler先執(zhí)行,然后頁面上會執(zhí)行頁面上所有Validator 控件的Validator方法,然后設(shè)置頁面的IsValid屬性。 2.如果該Event本身直接導(dǎo)致了Validation,比如用戶點擊了一個Button,這個Button默認就會導(dǎo)致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í)行一些清理工作。 |
下面將頁面生命周期與服務(wù)器控件生命周期在一張圖上(從MSDN中復(fù)制)綜合展示:

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:當服務(wù)器空間初始化時發(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:當服務(wù)器控件加載到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)容進行最后更改(預(yù)呈現(xiàn))");
i++;
Response.Write("");
}
protected void Page_PreRenderComplete(object sender, EventArgs e)
{
Response.Write(i + ".PreRenderComplete:呈現(xiàn)內(nèi)容前發(fā)生.(預(yù)呈現(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 服務(wù)器控件都有一個用于寫出發(fā)送給瀏覽器的控件標記的 Render 方法。*/
/*當你關(guān)閉頁面的時候就會引發(fā)UnLoad(當服務(wù)器控件從內(nèi)存中卸載時發(fā)生)
和Disposed兩事件(當從內(nèi)存釋放服務(wù)器控件時發(fā)生,這是服務(wù)器控件生存期的最后階段)
首先加載UnLoad事件:卸載頁面:完全呈現(xiàn)頁、將頁發(fā)送至客戶端并準備丟棄時,
將調(diào)用卸載。此時,將卸載頁屬性(如Response和Request)并執(zhí)行清理.
最后加載Disposed事件,釋放資源,生命周期結(jié)束....
*/
}
}結(jié)果顯示:

四、PageLoad 與 OnLoad區(qū)別:
1、用VS.Net生成的頁面中的Page_Load方法(事件處理程序)就是響應(yīng)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和所有服務(wù)器控件的基類),是在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請求,服務(wù)器windows內(nèi)核中的HTTP.SYS組件接收該請求開始到IIS處理完該請求并響應(yīng)到客戶端結(jié)束。

2、第二張圖片為圖1中Http處理管線的詳細步驟

3、 第三張圖片為圖2Http處理管線中調(diào)用處理程序(HttpHandler, 此處為Page對象)的詳細生命周期過程。

到此這篇關(guān)于ASP.Net頁面生命周期與Page_Load方法的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
使用vs2022在.net6中調(diào)試帶typescript的靜態(tài)頁面
這篇文章介紹了使用vs2022在.net6中調(diào)試帶typescript的靜態(tài)頁面,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-12-12
WPF框架Prism中ViewModelLocator用法介紹
這篇文章介紹了WPF框架Prism中ViewModelLocator的用法,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-02-02
IIS部署ASP.NET?Core項目及常見問題總結(jié)
這篇文章介紹了IIS部署ASP.NET?Core項目的方法及常見問題總結(jié),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-01-01

