ASP.NET頁面執行順序(第二個LoadViewState事件可以解釋我新浪博客中的“HiddenField隱藏域的值改變時onvaluechanged的事件觸發問題”一文的問題)


原文地址:http://blog.csdn.net/a497785609/article/details/4510335

1.對象初始化(OnInit方法)

    頁面中的控件(包括頁面本身)都是在它們最初的FORM中被首次初始化的。通過在ASPX頁面的后台代碼文件的構造器中聲明你的對象,頁面將知道對象的類型,並知道需要創建多少個這樣的對象。一旦你在構造器中聲明了你的控件,你就可以在它的任何子類,方法,事件或者屬性中訪問到它們。但是,如果你的任何對象是在ASPX文件中指定的控件,這樣的控件是沒有屬性的。而且這樣做對從代碼中訪問它們是危險的,因為無法保證這些控件實例是按照怎樣的順序被創建的(假定它們都是能完全被創建的)。初始化事件可以通過OnInit方法重載。

 

2.加載視圖狀態數據(LoadViewState事件)

   初始化以后,控件僅能通過ID引用(還沒有建立用於相對引用的文檔對象模型)。 在LoadViewState事件中,已初始化的控件獲得第一個屬性:上一次提交存留到服務器的視圖狀態信息(HiddenField。頁視圖狀態(ViewState)通過ASP.NET維護,它被用於在一個往返行程中存留信息到服務器。視圖狀態信息被保存為一個名稱/值對,它包含控件的如Text和Value一類的信息。視圖信息被保存在隱藏<input>控件的值屬性中在頁請求中傳遞。正如你所了解的,這是舊的ASP3.0狀態維護技術的一個巨大飛躍。這個事件可以通過LoadViewState方法重載,往往用來在控件被填充時定制它所接受的數據。

 

3.處理回傳數據(LoadPostData事件)

    在創建頁的階段,被發送到服務器端的Form數據(ASP.NET中的術語為回傳數據)依照每個控件的數據需求進行處理。當頁面提交Form時,框架將在每個提交數據的控件上實現IPostBackDataHandler接口。頁面然后激發LoadPostData事件,通過頁面解析發現實現了IPostBackDataHandler接口的控件,並用正確的回傳數據更新控件狀態。ASP.NET通過匹配控件的唯一標示符來更新正確的控件,該標示符具有名稱值集合中的名稱值對。這也就是在所有特定的頁中每個控件都需要一個唯一標示符的原因之一。其它的步驟都由框架來完成,以確定每個標示符在環境中是唯一的,例如存在於單頁面中的自定義用戶控件。LoadPostData事件被激發后,RaisePostDataChanged事件就可以隨時被執行了。

 

4.對象加載(OnLoad方法)

    對象在Load事件中獲得正確的Form。所有的對象首先都被組織在頁DOM(ASP.NET中稱為控件樹)中,並且很容易通過代碼或者相對位置(crawling the DOM)來引用。然后對象就可以自由的訪問HTML中的客戶端屬性集,例如width,value,或者visibility。加載時,控件邏輯,如算法、以編程方式設置控件屬性、用StringBuilder裝配輸出字符串都同時被執行。大部分的工作都是在這一階段完成的。Load 事件能夠通過調用OnLoad來重載。

 

5.激發RaisePostDataChanged 事件

    如前所述,這發生在所有實現了IPostBackDataHandler接口的控件被正確的回傳數據更新以后。在這個過程中,每個控件都有一個布爾值的標識,標識其自上一次提交后該控件的數據是被更改還是保持原值。然后ASP.NET通過搜索頁來尋找任何顯示控件數據被更改的標識並激發RaisePostDataChanged。RaisePostDataChanged事件直到Load事件發生后,所有控件被更新后才激發。這保證了在控件被回傳數據更新前,其它控件的數據在RaisePostDataChanged事件中沒有被手動更改過。

 

6.處理客戶端回傳事件(RaisePostBackEvent事件)

   當回傳更新導致數據改變而引發服務器端事件后,引發回傳的對象會在RaisePostBackEvent事件中被處理。這種激發回傳的對象往往是其狀態改變而引發回傳的控件(其autopostback被啟用)或者是一個被點擊的窗體提交按鈕。很多代碼都在這個事件中執行,因為這是控制事件驅動邏輯的理想位置。為了保證呈現到瀏覽器的數據的正確性,在一系列的回傳事件后RaisePostBackEvent事件最終被激發。基於一致性的考慮,回傳中改變的控件直到這個函數被執行后才被更新。也就是說,被預期事件改變的數據總是在結果頁反映出來。RaisePostBackEvent事件可以通過RaisePostBackEvent來捕捉。

 

7.對象預呈現(OnPreRender事件)

   對象被預呈現的地方對於那些能夠保存到視圖或者維持其視圖狀態的對象來說是最后一次有機會改變的地方。這使得預呈現步驟成為做最后修改的理想位置,例如改變控件屬性或改變控件樹結構,不用擔心因為數據庫請求或者視圖狀態更新而導致對象的變化。預呈現階段之后,對象改變被鎖定並且不能再被保存到頁視圖狀態中。預呈現階段可以通過重載OnPreRender實現。

 

8.保存視圖狀態(SaveViewState事件)

   只有在所有的頁面對象的改變都發生后視圖狀態才被保存。對象狀態數據被保存在隱藏<input>對象中,這也是對象狀態數據准備呈現到HTML的地方。在SaveViewState事件中,值能夠被保存到視圖狀態對象中,但頁面控件的改變並不能保存到其中。可以通過重載SaveViewState實現這個步驟。

 

9.呈現HTML(Render事件)

    Render事件通過裝配用於瀏覽器輸出的HTML來着手頁的創建。在Render事件中,頁調用對象使它們呈現為HTML,然后頁收集HTML來發送。當Render事件被重載的時候,開發者可以為瀏覽器創建定制的HTML,此時頁面創建的任何HTML都還沒有生效。Render 方法用HtmlTextWriter對象作參數並由它產生HTML給瀏覽器。這里仍然可以作修改,但是這樣的修改只會反映到客戶(譯者注:意即改變只會在HTML呈現中反映而視圖狀態並無法被改變)。Render 事件可以被重載。

 

10.釋放(Dispose事件)

當頁面的HTML呈現后,對象被釋放。在Dispose事件中,你可以清除任何在頁面創建中構造的對象或者引用。在這里,所有的處理都已經被執行,你可以安全的釋放任何還存在的對象,包括Page對象。Dispose能被重載。

具體對應的事件順序如下:

①Page_Init()     對象初始化;

②LoadViewState   加載視圖狀態;

③LoadPostData    處理回送數據;

④Page_Load()     頁面加載;

⑤RaisePostDataChanged  數據更新並回送事件;

⑥RaisePostBackEvent    處理客戶端回傳的事件;

⑦Page_PreRender()頁面預處理;

⑧SaveViewState   保存視圖狀態;

⑨Page_Render()   呈現Html靜態頁面;

⑩UnLoad          釋放頁面;

 

總結

每次我們請求一個ASP.NET頁的時候,這個從初始化到釋放的過程都同樣的被執行。通過理解ASP.NET頁的內部執行過程,編寫和調試代碼的時候就會更加容易和高效。

下面是具體的代碼:

 
using System;  
using System.Data;  
using System.Configuration;  
using System.Web;  
using System.Web.Security;  
using System.Web.UI;  
using System.Web.UI.WebControls;  
using System.Web.UI.WebControls.WebParts;  
using System.Web.UI.HtmlControls;  
  
public partial class _Default : Page   
{  
    protected void Page_Load(object sender, EventArgs e)  
    {  
  
    }  
 
    #region OnPreInit 第一步   
    protected override void OnPreInit(EventArgs e)  
    {  
        //檢查 IsPostBack 屬性來確定是不是第一次處理該頁。   
        //創建或重新創建動態控件。   
        //動態設置主控頁。   
        //動態設置 Theme 屬性。   
        //讀取或設置配置文件屬性值。   
        //注意     
        //如果請求是回發請求,則控件的值尚未從視圖狀態還原。如果在此階段設置控件屬性,則其值可能會在下一事件中被重寫。   
        base.OnPreInit(e);  
    }  
    #endregion  
 
    #region OnInit 第二步   
    protected override void OnInit(EventArgs e)  
    {  
        //在所有控件都已初始化且已應用所有外觀設置后引發。使用該事件來讀取或初始化控件屬性。   
        base.OnInit(e);  
    }  
    #endregion  
 
    #region OnInitComplete 第三步   
    protected override void OnInitComplete(EventArgs e)  
    {  
        //由 Page 對象引發。使用該事件來處理要求先完成所有初始化工作的任務。   
        base.OnInitComplete(e);  
    }  
    #endregion  
 
    #region PreLoad 第四步   
    protected override void OnPreLoad(EventArgs e)  
    {  
        //如果需要在 Load 事件之前對頁或控件執行處理,請使用該事件。    
        //在 Page 引發該事件后,它會為自身和所有控件加載視圖狀態,然后會處理 Request 實例包括的任何回發數據。   
        base.OnPreLoad(e);  
    }  
    #endregion   
 
    #region OnLoad 第五步   
    protected override void OnLoad(EventArgs e)  
    {  
        //Page 在 Page 上調用 OnLoad 事件方法,然后以遞歸方式對每個子控件執行相同操作,如此循環往復,直到加載完本頁和所有控件為止。   
        //使用 OnLoad 事件方法來設置控件中的屬性並建立數據庫連接。   
        base.OnLoad(e);  
    }  
    #endregion  
 
    #region 控件事件 第六步   
    protected void Button1_Click(object sender, EventArgs e)  
    {  
        //用這些事件來處理特定控件事件,如 Button 控件的 Click 事件或 TextBox 控件的 TextChanged 事件。   
        //注意     
        //在回發請求中,如果頁包含驗證程序控件,請在執行任何處理之前檢查 Page 和各個驗證控件的 IsValid 屬性。   
  
    }  
    #endregion  
 
    #region OnLoadComplete 第七步   
    protected override void OnLoadComplete(EventArgs e)  
    {  
        //對需要加載頁上的所有其他控件的任務使用該事件。   
        base.OnLoadComplete(e);  
    }  
    #endregion  
 
    #region OnPreRender 第八步   
    protected override void OnPreRender(EventArgs e)  
    {  
        //在該事件發生前:   
        //Page 對象會針對每個控件和頁調用 EnsureChildControls。    
        //設置了 DataSourceID 屬性的每個數據綁定控件會調用 DataBind 方法。有關更多信息,請參見下面的數據綁定控件的數據綁定事件。   
        //頁上的每個控件都會發生 PreRender 事件。使用該事件對頁或其控件的內容進行最后更改。   
        base.OnPreRender(e);  
    }  
    #endregion   
 
    #region SaveStateComplete 第九步   
    protected override void OnSaveStateComplete(EventArgs e)  
    {  
        //在該事件發生前,已針對頁和所有控件保存了 ViewState。將忽略此時對頁或控件進行的任何更改。   
        //使用該事件執行滿足以下條件的任務:要求已經保存了視圖狀態,但未對控件進行任何更改。   
        base.OnSaveStateComplete(e);  
    }  
    #endregion  
 
    #region Render 第十步   
    //Render   
    //這不是事件;在處理的這個階段,Page 對象會在每個控件上調用此方法。所有 ASP.NET Web 服務器控件都有一個用於寫出發送給瀏覽器的控件標記的 Render 方法。   
    //如果創建自定義控件,通常要重寫此方法以輸出控件的標記。不過,如果自定義控件只合並標准的 ASP.NET Web 服務器控件,不合並自定義標記,則不需要重寫 Render 方法。有關更多信息,請參見開發自定義 ASP.NET 服務器控件。   
    //用戶控件(.ascx 文件)自動合並呈現,因此不需要在代碼中顯式呈現該控件。  
    #endregion  
 
    #region OnUnload 第十一步          
    protected override void OnUnload(EventArgs e)  
    {  
        //該事件首先針對每個控件發生,繼而針對該頁發生。在控件中,使用該事件對特定控件執行最后清理,如關閉控件特定數據庫連接。   
  
        //對於頁自身,使用該事件來執行最后清理工作,如:關閉打開的文件和數據庫連接,或完成日志記錄或其他請求特定任務。   
        //注意     
        //在卸載階段,頁及其控件已被呈現,因此無法對響應流做進一步更改。如果嘗試調用方法(如 Response.Write 方法),則該頁將引發異常。   
        base.OnUnload(e);  
    }  
    #endregion   
}  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM