ASP.NET 頁面生命周期
Page_Preinit(); 在頁初始化開始時發生
Page_Init(); 在所有控件初始化且應用外觀設置後引發
Page_InitComplete(); 在頁初始化完成時發生
Load ViewState and Postback data; //加載視圖和回傳數據
Page_Preload(); 在load事件之前發生
Page_Load(); 服務器控件加載到page對象時發生
LoadCompleteLoadComplete(); 在所有回發數據和視圖狀態數據都加載到頁以及頁上的所有控件中後發生
Handle control events; //處理控件事件
Page_PreRender(); 在加載Control對象後,呈現之前發生
Page_Render(); Render 方法負責創建的文本和發送到客戶端浏覽器的標記。
Unload event; 當服務器控件從內存中卸載時發生,該事件先針對每個控件然後針對整頁
Dispose method called;
asp.net頁面生命周期
--------------------------------------------------------------------------------
頁面執行是從FrameworkInitialize方法開始的,這個方法為頁面構建控件樹。該方法是TemplageControl類的受保護並且是虛方法。任何為aspx資源動態生成的句柄覆蓋了該方法。在這個方法裡,頁面的所有控件樹都被構建了。
接下來,ProcessRequest方法使頁面經歷了不同的幾個階段:初始化、加載視圖狀態信息、回傳數據、加載頁面代碼和執行回傳的服務器事件。在這之後,頁面轉換到了顯示模式:收集被更新的視圖狀態;產生HTML代碼,並且傳送到控制台。最後,頁面卸載,請求的全部服務結束了。
在各個不同階段裡,頁面處理了與web控件相關、程序員代碼能夠干預並解決一定問題的事件。其間一些事件是專門為那些內嵌控件和不能在.aspx代碼級別處理的控件而設計的。
一個頁面要解決這樣的事件,它能明確的注冊成為合適的句柄。但是,為了和原有的Visual Basic編程模式有後向兼容性,ASP.NET也支持了隱含事件的形式。在默認情況下,頁面會尋找和事件相關的方法名;如果找到和事件相匹配的方法,這個方法就被認為是這種事件的處理程序。ASP.NET提供了六種專門的方法名,他們是 Page_Init , Page_Load , Page_DataBind , Page_PreRender 和 Page_Unload 。這些方法這些方法在Page類中已經被定義過,他們是相應事件的處理程序。HTTP運行時將自動的將這些方法綁定到相關的頁面事件,而不需要程序員去編寫把事件和方法聯系起來的代碼。舉個例子來說,在下面的代碼中, Page_Load方法和頁面的加載事件相關聯:
this.Load + = new EventHandler(this.Page_Load);
這種自動識別是被 @Page 預指令的AutoEventWireup 屬性控制的。如果這個屬性被置false ,應用程序必須顯式聲明和事件相關的方法。不自動關聯頁面事件代碼的頁面執行起來會快一些,是因為他們不需要在匹配上做過多的工作。在Visual Studio.NET 工程裡可以把這個屬性關閉掉。但是,默認設置是true,這意味著Page_Load方法被自動識別並被關聯到相關的事件。
頁面執行包含了下表中按順序列出的幾個階段,他們被標志成為應用程序級別的事件,同時也可能是一些受保護、重定義的方法:
階段 頁面事件 可重定義的方法
頁面初始化 Init
視圖狀態加載 LoadViewState
回傳數據處理 控件裡實現了IPostBackDataHandler接口的LoadPostData方法
頁面加載 Load
回傳數據變化檢查 控件裡實現了IPostBackDataHandler接口的RaisePostDataChangedEvent方法
回傳事件處理 控件裡定義的回傳事件 控件裡實現了IPostBackEventHandler接口的RaisePostBackEvent方法
頁面預返回階段 PreRender
頁面返回階段 Render
頁面卸載階段 Unload
上表中列出的階段有的在頁面級別是不可見的,他們只是在服務器控件的作者編寫繼承於Page的類時會使用到。Init , Load , PreRender , Unload,再加上定義在內嵌控件中的回傳處理事件,他們構成了頁面的整個生命周期。
各個階段的執行
頁面生命周期的第一階段是初始化。這個階段被Init事件所描述,這個事件在控件樹被構建出來後執行。換句話說,當Init事件發生時,所有在.aspx文件中靜態聲明的控件被實例化並被賦予了默認值。在Init事件中可以初始化任何的在頁面生命周期裡需要的設置。例如:在這個階段,控件可以加載外部的摸版文件或者是為事件建立處理句柄。需要注意的是,任何的視圖狀態信息在這個階段裡是不能用的。
緊接著初始化結束後,頁面構架為頁面加載視圖狀態。視圖狀態是 名稱/值 對的集合,控件或頁面在這裡保存的數據在整個web請求過程中必須是穩固的。視圖狀態代表著頁面的上下文。典型的,它保存著頁面上次在服務器上被執行時控件的狀態。視圖狀態在會話開始的第一個頁面請求時是空的。在默認情況下,試圖狀態被保存在一個隱藏域裡,這個隱藏域是被自動添加到頁面裡的。這個隱藏域的名稱是 __VIEWSTATE。如果覆蓋了LoadViewState方法——在Control類裡被聲明為受保護的方法——組件開發者可以控制視圖狀態的保存和它是如何和內部狀態形成映射。
象LoadPageStateFormPersistenceMedium這樣的方法和與其相對應的SavePageStateToPersistenceMedium方法可以用來加載或者保存視圖狀態到其他的存儲中介裡,例如:會話、數據庫或者是服務器上的文件。和LoadViewState方法不相同的是,上面提到的方法只能在Page的繼承類裡使用。
一旦視圖狀態加載完畢了,頁面裡的控件被賦予了和上一次發送到浏覽器時一樣的狀態。下一個階段是將他們更新,使之與服務器端發生的變化相一致。在回傳數據處理階段,控件更新他們的狀態,使之和客戶端的HTML元素的狀態相一致。例如,服務器控件TextBox有和它相對應的HTML控件<input type=text>。在回傳數據階段,TextBox控件將得到<input>標簽的值,並且用他來更新他的內部狀態。每一個控件都可以從回傳數據中取得自己數據的能力,並且把自己的狀態更新。TextBox控件將更新它的Text屬性,同樣的,CheckBox控件也會將他們的Checked屬性刷新。服務器控件和HTML元素的匹配是通過兩者的ID來進行的。
在回傳數據處理的最後階段,所有的頁面控件反映了上一個被更新的狀態,這些都是由於客戶端的輸入變化所引起的。接下來,Load事件將被頁面執行。
有一些控件,在兩次請求中如果某些敏感屬性發生了變化,他們需要對此作出響應,並且完成一定的任務。例如,如果客戶端的textbox控件的文本發生變化,這個控件就激發了TextChanged事件。根據自客戶端的數據,如果控件的一個或多個屬性發生了變化,每一個控件都可以精確的激發合適的事件來處理。這些控件實現了IPostBackDataHandler接口,這個接口中的LoadPostData方法在Load事件之後就被執行了。通過重定義LoadPostData方法,控件可以驗證兩次請求中發生的變化並且激起相關的事件處理程序。
在一個頁面周期中的關鍵事件是那些由客戶端事件激發在服務器執行一段代碼的事件。例如,當用戶點擊一個按鈕,頁面就需要回傳。這個事件的處理是從按鈕ID和值的收集開始的。如果控件是實現了IPostBackEventHandler接口(Button和LinkButton就是這樣的情況),頁面構架將調用RaisePostBackEvent方法。這個方法的具體情況是取決於控件的類型的。在上面提到的Button和LinkButton控件,這個方法就將尋找Click事件處理程序。
處理了回傳事件之後,頁面就准備被發送出去了。這個階段是從PreRender事件開始的。這對於控件來說,那些需要在視圖信息被保存與結果被發送之前這段時間裡執行的動作,這是一個很好的時機。下一步就是SaveViewState ,所有的空間和頁面本身就把視圖狀態的集合內容保存起來。接下來,視圖狀態被串行化、哈希編碼、Base64 編碼,並且保存在__VIEWSTATE隱藏域裡。
各個控件的發送機制可以通過重定義Render方法來改變。這個方法構建了一個HTML writer對象,用它來為控件產生HTML代碼。對Page類裡Render方法的默認執行包含了對所有成員控件的遞歸調用。頁面為每一個控件調用一次Render方法,並緩沖HTML輸出。
頁面生命周期的最後階段是卸載事件,這個事件在頁面對象消失前被激發。在這個事件裡,你應該把任何臨界資源釋放掉(例如:文件、圖形對象、數據庫連接)。
最後,浏覽器接收到了HTTP響應,並且把頁面顯示出來。
博客園chunchill博主的文章詳細講解了每個階段的工作:http://www.cnblogs.com/shineqiujuan/archive/2008/09/22/1295845.html
另附上MSDN官方文檔: https://msdn.microsoft.com/zh-cn/library/ms178472.aspx
本文參考 CSDN知識庫 http://lib.csdn.net/article/dotnet/53573
轉載請標明鏈接