1. 程式人生 > >.net頁面生命週期

.net頁面生命週期

       ASP.NET 頁執行時,此頁將經歷一個生命週期,在生命週期中將執行一系列處理步驟。這些步驟包括初始化、例項化控制元件、還原和維護狀態、執行事件處理程式程式碼以及進行呈現。瞭解頁的生命週期非常重要,這樣就能在合適的生命週期階段編寫程式碼,以達到預期效果。此外,如果開發自定義控制元件,則必須熟悉頁生命週期,從而正確地初始化控制元件,使用檢視狀態資料填充控制元件屬性以及執行所有控制元件行為邏輯。
      

    (1)物件初始化Init事件:頁面初始化的標誌是Init事件。頁面中的控制元件(包括頁面本身)都是在它們最初的Form中被首次初始化的。在成功建立頁面的控制元件樹後,對應用程式激發這個事件。當Init事件發生時,在.aspx原始檔中靜態宣告的所有控制元件都以例項化並取其預設值。應該注意到,這是還沒有檢視狀態資訊可供使用。雖然可以過載OnInit方法,但是系統並不保證這些控制元件例項是按照怎樣的順序被建立的。

    (2)載入檢視:在初始化之後,頁面框架立即載入該頁面的檢視狀態(ViewState)。所謂檢視狀態就是一些名稱/值對的集合,例如可以儲存TextBox控制元件的ID和Text屬性值。它一般被用於在一個往返行程中存留資訊到伺服器,即參與HTTP請求與響應。

頁面檢視狀態被儲存在<input type=”hidden”>欄位中,做為_VIEWSTAE的值進行記錄。該檢視狀態通過ASP.NE自動維護。通過重寫LoadViewState方法元件,開發人員可控制如何還原檢視狀態以及如何將其內容影射到內部狀態。LoadViewState方法就是從ViewState中獲取上一次的狀態,並按照頁面的控制元件樹的結構,用遞迴來遍歷整個樹,將對應的狀態恢復到每一個控制元件上。

    (3)處理回發資料:還原了檢視狀態,頁面樹種的各個控制元件的狀態就與瀏覽器上次呈現該頁面時這些控制元件所處的狀態相同。下一步需要更新這些控制元件的狀態以傳送給客戶端。

回發資料處理階段是各個控制元件有機會更新其狀態,以便準確的反映相應的HTML元素在客戶端的狀態。例如,一個伺服器TextBox控制元件對應的HTML元素是<input type=text>,在回發資料階段,TextBox控制元件將檢索<input>標記的當前值並用它重新整理其內部狀態。每個控制元件負責從以傳送的資料中提取相應值,並更新其某些屬性。TextBox控制元件將更新Text屬性,而CheckBox控制元件將重新整理其Checked屬性。伺服器控制元件和HTML元素之間的匹配關係由二者的ID確定。

頁框架將在每個提交資料的控制元件上實現IpostBackDataHandler介面,然後激發LoadPostData事件,通過頁面解析發現實現了IpostBackDataHandle介面的控制元件,這樣就能正確的回傳資料更新控制元件狀態。在識別控制元件時,ASP.NET通過匹配控制元件的唯一標示符來更新正確的控制元件,該識別符號具有名稱值集和中的名稱值對。這也就是在所有特定的頁中每個控制元件都需要一個唯一識別符號的原因之一。其他的步驟都由框架來完成,例如確定每個識別符號在環境中是否唯一以及控制元件的基本屬性等。

LostPostData方法的原型如下:

Public virtual bool LoadPostData(string postDatakey, NameValueCollection postCollection)

PostDataKey是標識控制元件的關鍵字,可以理解為控制元件的ID,postCollection是包含回發資料的集合,可以理解為檢視狀態值。該方法返回一個bool值,如果是true,則表示控制元件狀態因回發而更改;否則返回false。頁框架會更跟蹤所有返回true的控制元件並在這些控制元件上呼叫RaisePostDataChangeEvent事件。

LoadPostData方法是由System..Web.WebControls.Control定義的,而新增的每一個伺服器控制元件也是從System..Web.WebControls.Control繼承的,所以對於資料的回發處理並不需要干預。

    (4)載入頁面Load:在回發資料處理階段結束時,頁面中的所有控制元件都根據客戶端上所輸入的更改來更新的狀態。此時,對頁面激發OnLoad事件。對於這個事件,相信大多數朋友都會比較熟悉,用Visual Studio.Net生成的頁面中的Page_Load方法就是響應Load事件的方法,對於每一次請求,Load事件都會觸發,Page_Load方法也就會執行。可以利用該方法執行一些頁面初始化,例如準備好資料庫的連線字串。在事件引用中,為了提高效能,通常使用Page類的IsPostBack屬性判斷是不是資料回發。

    (5)回發更改通知RaisePostDataChanged:如(3)所述,在所有實現了IpostBackDataHandler介面的控制元件被正確的回傳資料更新後,每個控制元件都有一個布林值的標識,標識其自上一次提交後改控制元件的資料是被更改還是保持其值。然後ASP.NET通過搜尋頁來尋找任何顯示控制元件資料被更改的標識並激發RaisePostDataChanged。RaisePostDataChanged事件直到Load事件發生後,所有控制元件被更新後才激發。這保證了在控制元件被回傳資料更新前,其他控制元件的資料在RaisePostDataChanged事件中沒有被手動更改過。雖然也可以在Page的基礎上自己定義資料更改的事件,但通常這個事件由太大用處。

    (6) 處理回發事件RaisePostBackEvent:當回傳更新導致資料改變而引發伺服器端事件後,引發回傳的物件會在RaisePostBackEvent事件中被處理。這種引發回傳的物件往往是一個按鈕被單擊或者其狀態改變而引發回傳的控制元件。例如Button觸發樂Onclick事件、客戶端修改了某個文字框的文字、同時將AutoPostBack設定為true、觸發TextChanged事件等。

很多程式碼都在這個事件中執行,因為這是控制事件驅動邏輯的理想位置。為了保證呈現到瀏覽器的資料的正確性,在一系列的回傳事件後,RaisePostBackEvent事件最終被激發。基於一致性考慮,會傳中改變的控制元件直到這個函式被執行後才被更新。在實際的ASP.NET開發工作中要做的工作就是在此事件發生前處理程式碼。

    (7)預呈現PreRender:在處理回發事件後,頁面就準備進行呈現。這一階段的標誌是PreRender事件。各個控制元件可利用這個很好的時機,以便執行任何需要在儲存檢視狀態和呈現輸出結果的前一刻完成得最後一些更新操作。最終請求的處理都會轉變為發揮伺服器的響應,預呈現這個階段就是執行在最終呈現之前所做的狀態的更改,因為在呈現一個控制元件之前,必須更具它的屬性來產生HTML,比如Style屬性。這是典型的例子,這預呈現之前,可以更改一個控制元件的Style,當執行預呈現時,就可以把Style儲存下來,做為呈現階段顯示HTML的樣式資訊。

    (8)儲存狀態SaveViewState:下一個狀態為SaveViewState,在這一狀態中所有控制元件以及頁面本身可以重新整理自己的SaveState集合的內容。所得到的檢視狀態隨後得以序列化、進行雜湊運算、進行Base64編碼並關聯到VI-EMSTATE隱藏自端。

    (9)呈現檢視Render:到這裡,實際上頁面對請求的處理基本就告一段落了,在Render事件中,也呼叫物件是它們呈現為HTML,然後也收集HTML傳送給客戶。客戶接收到HTML標記後進行重組,最終顯示給客戶。當Render事件被過載時,開發者可以為瀏覽器建立定值的HTML,此時頁面建立的任何HTML都還沒有生效。Render方法用HtmlTextWriter物件做引數並由它產生HTML送給瀏覽器。這主要用於自定義控制元件的開發。

    (10)處置Disposed:執行銷燬控制元件前的所有最終清理操作。在此階段必須釋放對昂貴資源的引用,如記憶體的退出、資料庫的連線等。

    (11) 解除安裝Unload:一個頁面的最後生存標誌就是Unload事件,該事件在頁面物件被解除之前發生。在此事件中,可以呼叫Dispose方法儘可能釋放佔用的任何關鍵資源(例如,檔案、圖形物件以及資料庫連線)。