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