ASP.NET页面揭秘之页面生命周期
首先簡單介紹下Page類。
在.NET Framework中,Page類提供了ASP.NET應用程序從.aspx文件開始創建的所有對象的基本行為。Page類在System.Web.UI命名空間中定義,它派生于TemplateControl類并實現了IHttpHandler接口。TemplateControl類是一個抽象類,它為 Page 類和 UserControl 類提供通用屬性和方法。
由于Page類派生于一個是實現了INamingContainer接口的類,Page類還充當它的所有組成控件的容器。一個控件命名容器實現了INamingContainer接口的第一個父控件。對于任何一個實現了命名容器接口的類,ASP.NET創建一個新的虛擬命名空間,其中保證所有的子控件在整個控件樹有唯一的名稱。通俗點INamingContainer接口無任何方法,知識保證其子控件有唯一的名稱。
Page類實現IHttpHandler接口的方法,從而可以充當一種特殊類型的HTTP請求(.aspx文件的請求)的處理程序。ASP.NET運行庫調用ProcessRequest方法用來處理請求。
在ASP.NET頁面中,runat屬性設置為server的任何控件都不能放在<form>標簽外。那么是怎么做到確定所有控件不在form外的呢?可以用Page類的VerifyRederingInSeverForm()方法。控件在生成時調用該方法,以確保服務器窗體的主體包含它們。該方法不返回一個值,但是出錯的情況下會拋出一個異常。
?
在ASP.NET頁面揭秘(一)中我們提到執行和觸發ProcessRequest調用的步驟和事件過程統稱為頁面生存周期。其實HTTP運行庫激活ProcessRequest時便開始執行頁面,ProcessRequest啟動頁面并控制生命期
頁面生命期分三個階段:建立階段,回發階段,結束階段。每個階段有一個或多個子階段,并且有一個或多個事件和步驟引發組成。
一 頁面的建立
當HTTP運行庫實例化頁面類以便為當前提供服務時,頁面構造器創建一個控件樹。該控件樹連接到頁面解析器在查看ASPX源文件后所創建的實際類。處理請求開始時,應設置所有的子控件和頁面本征特征(如HTTP上下文,請求對象和響應對象)。
頁面生命期第一步是確定為什么運行庫正在處理頁面請求。其中原因有多樣:正常請求,回發,跨頁回發或者回叫。頁面對象根據具體原因配置內部狀態,并根據請求方法(GET或POST)準備投遞的值集合(post value)。這部完成后,頁面就準備激發用戶代碼事件。
1.PreIntit事件
它是頁面生命周期進入點。該事件激發時,頁面還沒有關聯任何的母版頁和主題。頁面滾動位置已經恢復,投遞的數據可以用,并且所有的頁面控件已經被實例化且默認地取ASPX源文件中定義的屬性值(注意這時控件沒有ID,除非在.aspx源文件中顯式地設置它)只有這時才可以通過編程方式修改母版頁或主題。該事件只有在頁面上可用。IsCallBack(該值指示頁請求是否是回調的結果),IsCrossPagePostback(獲取一個值,該值指示跨頁回發中是否涉及該頁)和IsPostback(獲取一個值,該值指示該頁是否正為響應客戶端回發而加載,或者它是否正被首次加載和訪問)都在這時設置其值。
2.Init 事件
這時已經設置母版頁和主題,并且不能修改。頁面處理器,即Page類上的ProcessRequest方法,遍歷所有的子控件,使他們有機會以一種上下文相關的方法初始化它們的狀態。所有的子控件遞歸地調用它們的OnInit方法。為控件集合中的每個控件設置命名容器和一個具體的ID。Init事件首先到達子控件,然后到達頁面。這個階段,頁面和控件通常開始加載他們的部分狀態。然而這時沒有恢復視圖狀態。
3.IntiComplete事件
這個只有頁面才有的事件,表明初始化子階段的結束。在Init 事件和IntiComplete事件之間只發生一個操作:打開視圖狀態變更的跟蹤功能。它始終使控件能夠真正地把所有以編程方式添加到ViewState結合中的數值持久地存儲在存儲介質中。即沒有打開跟蹤狀態的控件,任何添加到ViewState的值將會在下一次回發時丟失。所有控件在發出Inti事件后立即打開視圖狀態跟蹤,頁面也不例外。
4.視圖狀態恢復
如果頁面由于回發處理,則恢復VIEWSTATE隱藏字段內容。_VIEWSTATE隱藏字段保存著一個請求結束時所有控件視圖狀態。頁面的總體視圖狀態是一種調用上下文,包含頁面最后一次服務器時每個組成控件的狀態。(ViewState個可以留到控件相關的知識里介紹)
5.處理投遞的數據
HTTP請求中包裝的所有用戶數據,即用<form>標簽定義的所有輸入字段的內容,都在這時進行處理。投遞的數據通常采取如下格式:
????? TextBox1=text&DropDownList1=selectedItem&Button1=Submit
這是一串用&隔開的名稱/值對。這些值裝入一個內部使用的集合。頁面處理器視圖將投遞的數據集合中的名稱與頁面中的控件的ID進行匹配。每找到一個匹配,處理器檢查該服務器控件有沒有實現 IPostBackDataHanlder接口。如果實現了,則調用該接口的LoadPostData方法,該控件有機會根據投遞的數據刷新它的狀態。具體說,如果LoadPostData()方法返回true,即狀態已被更新,則把該控件添加到一個不同的集合中,以便以后引起關注。
(注:LoadPostData實現IPostBackDataHandler(實現控件數據回傳必須要繼承該接口)的一個方法,該方法參數NameValueCollection類型的對象裝載了客戶端提交的數據。另外該方法還會比較控件的舊值和新值返回一個bool類型值,以決定是否執行RaisePostDatachangedEvent方法,即跟新控件里的值,詳細請看深入理解.net服務器控件)
如果一個發送的名稱與任何一個服務器控件都不匹配,則留下它并臨時放在一個不同的集合中,稍后再試。
6.PreLoad事件
它指頁面已經結束系統初級初始化階段,并且準備進入下一個階段,即還有機會在該頁面中的用戶代碼中配置頁面的執行和呈現。
7.Load事件
首先它針對頁面的引發,然后遞歸針對所有的子控件引發。頁面中的控件在此時創建,并且他們的狀態完全反映前一個狀態以及從客戶端發送的任何數據。頁面準備執行所有與頁面邏輯和行為有關的初始化代碼。這時,訪問控件屬性和視圖狀態是絕對安全的。
8處理動態創建的控件
如果在顯示前,頁面中的所有控件都有機會完成初始化,頁面處理器將再次嘗試匹配那些尚未與現有控件匹配的投遞值。這主要是應對動態的創建的控件
設想把一個控件動態地添加到頁面樹上,例如為了響應某個用戶動作。每次回發以后重新創建頁面,因此與動態創建的控件有關的任何信息會丟失。另一方面,提交頁面的窗體時,其中的動態控件定期發送的合法而有效地信息填充。根據設計,第一次投遞的數據時,不可能有什么服務器控件匹配動態控件ID。然而,ASP.NET Fromework知道Load事件會創建某些控件。因此有了再次匹配這一說。如果動態控件已經在Load事件中被重建了,現在就可以找到一種匹配,并且該控件可以用投遞的數據刷新狀態。
?
二 處理回發
回發機制它涉及到把窗體數據投遞到相同頁面,然后使用視圖狀態恢復調用上下文,在服務器上最后一次生成投遞頁時存在的控件的同一種狀態。
在頁面初始化已經完成并已經考慮投遞的值以后,會發生某些服務器端事件。事件類型主要有兩種。
1.檢測控件狀態變化
整個ASP.NET工作機制圍繞一個隱含的假設:在瀏覽器中操作一些HTML輸入標簽與服務器控件具有一一對應關系。例:<input type=”text”>與<asp:TextBox>。當用戶把一些信息輸入到元素中后,調用對應的TextBox 控件來處理該投遞值。
對于讓LoadPostData方法返回true的所有控件,現在要執行RaisePostDataChangeEvent方法,該方法也屬于IPostBackDataHandler接口。該方法通知ASP.NET應用程序控件的狀態已經發生變化。
2.執行服務器端回發事件
任何回發都從某個打算觸發一個服務器端動作的客戶端動作開始。相信大家對回發事件應經很理解了這里不再多介紹。通俗的說就是能觸發服務器端的事件代碼的執行。
3.LoadComplete事件
表明頁面準備階段的結束。任何子控件都不會接受該事件。激發LoadComplete頁面進入呈現階段。
?
三 頁面結束
處理回發事件以后,頁面準備為瀏覽器生成輸出。
1.PreRender事件
通過處理該事件,頁面和控件可以在呈現輸出之前任何更新。PreRender事件首先為頁面激發,然后遞歸地為控件激發。
2.PreRenderConmplete事件
因為PreRender事件是遞歸地為所有子控件激發的,所以編程者無法知道何時完成預呈現階段。而該事件的激發代表上面的事件結束了。
3.SaveStateComple事件
在每個控件生成頁面的標記之前,把頁面的當前狀態保存到視圖狀態存儲介質。在頁面上的控件狀態已經全部保存到持久性質時,會觸發該事件。
4.生成標記
為瀏覽器生成標記是通過調用各組成控件來生成自己的標記來完成的,這些標記將存儲到一個緩沖區中。這個階段沒有任何用戶事件。
5.Unload事件
生成階段之后是一個遞歸調用,為每個控件引發Unload事件,并最終為頁面引發Unload事件。Unload事件存在的目的是在釋放頁面對象之前執行所有最后的清除工作。典型操作是關閉文件和數據庫連接。
?
相信這里看過之后再讀 深入理解.net服務器控件會有進一步理解
轉載于:https://www.cnblogs.com/30ErLi/archive/2010/09/19/1830713.html
總結
以上是生活随笔為你收集整理的ASP.NET页面揭秘之页面生命周期的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《ASCE1885的源码分析》の基于完成
- 下一篇: WCF面向服务应用程序系列之一:Hell