六月婷婷综合激情-六月婷婷综合-六月婷婷在线观看-六月婷婷在线-亚洲黄色在线网站-亚洲黄色在线观看网站

明輝手游網中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

ASP.Net Web Page深入探討二

[摘要]五、頁面生存周期現在回到第三個標題中講到的內容,我們講到了HttpApplication的實例接收請求,并創建頁面類的實例,實際上這個實例也就是動態編譯的ASPX的類的一個實例,上一個標題中我們了解到ASPX實際上是代碼綁定中類的子類,所以它繼承了所有的protected方法。現在我們來看看VS....

五、頁面生存周期

現在回到第三個標題中講到的內容,我們講到了HttpApplication的實例接收請求,并創建頁面類的實例,實際上這個實例也就是動態編譯的ASPX的類的一個實例,上一個標題中我們了解到ASPX實際上是代碼綁定中類的子類,所以它繼承了所有的protected方法。

現在我們來看看VS.Net自動生成的CodeBehind類的代碼,以此來開始我們對頁面生命周期的探討:

#region Web Form Designer generated code

override protected void OnInit(EventArgs e)

{

//

// CODEGEN:該調用是 ASP.NET Web 窗體設計器所必需的。

//

InitializeComponent();

base.OnInit(e);

}

/// <summary>

/// 設計器支持所需的方法 - 不要使用代碼編輯器修改

/// 此方法的內容。

/// </summary>

private void InitializeComponent()

{

this.DataGrid1.ItemDataBound += new System.Web.UI.WebControls.DataGridItemEventHandler(this.DataGrid1_ItemDataBound);

this.Load += new System.EventHandler(this.Page_Load);

}

#endregion

這個就是使用VS.Net產生的Page的代碼,我們來看,這里面有兩個方法,一個是OnInit,一個是InitializeComponent,后者被前者調用,實際上這就是頁面初始化的開始,在InitializeComponent中我們看到了控件的事件聲明和Page的Load聲明。

下面是從MSDN中摘錄的一段描述和一個頁面生命周期方法和事件觸發的順序表:

“每次請求 ASP.NET 頁時,服務器就會加載一個 ASP.NET 頁,并在請求完成時卸載該頁。頁及其包含的服務器控件負責執行請求并將 HTML 呈現給客戶端。雖然客戶端和服務器之間的通訊是無狀態的和斷續的,但是必須使客戶感覺到這是一個連續執行的過程。”

“這種連續性假象是由 ASP.NET 頁框架、頁及其控件實現的。回發后,控件的行為必須看起來是從上次 Web 請求結束的地方開始的。雖然 ASP.NET 頁框架可使執行狀態管理相對容易一些,但是為了獲得連續性效果,控件開發人員必須知道控件的執行順序。控件開發人員需要了解:在控件生命周期的各個階段,控件可使用哪些信息、保持哪些數據、控件呈現時處于哪種狀態。例如,在填充頁上的控件樹之前控件不能調用其父級。”

“下表提供了控件生命周期中各階段的高級概述。有關詳細信息,請點擊表中的鏈接。”

階段
控件需要執行的操作
要重寫的方法或事件

初始化
初始化在傳入 Web 請求生命周期內所需的設置。請參閱處理繼承的事件。
Init 事件(OnInit 方法)

加載視圖狀態
在此階段結束時,就會自動填充控件的 ViewState 屬性,詳見維護控件中的狀態中的介紹。控件可以重寫 LoadViewState 方法的默認實現,以自定義狀態還原。
LoadViewState 方法

處理回發數據
處理傳入窗體數據,并相應地更新屬性。請參閱處理回發數據。

注意 只有處理回發數據的控件參與此階段。
LoadPostData 方法

(如果已實現 IPostBackDataHandler)

加載
執行所有請求共有的操作,如設置數據庫查詢。此時,樹中的服務器控件已創建并初始化、狀態已還原并且窗體控件反映了客戶端的數據。請參閱處理繼承的事件。
Load 事件

(OnLoad 方法)

發送回發更改通知
引發更改事件以響應當前和以前回發之間的狀態更改。請參閱處理回發數據。

注意 只有引發回發更改事件的控件參與此階段。
RaisePostDataChangedEvent 方法

(如果已實現 IPostBackDataHandler)

處理回發事件
處理引起回發的客戶端事件,并在服務器上引發相應的事件。請參閱捕獲回發事件。

注意 只有處理回發事件的控件參與此階段。
RaisePostBackEvent 方法

(如果已實現 IPostBackEventHandler)

預呈現
在呈現輸出之前執行任何更新。可以保存在預呈現階段對控件狀態所做的更改,而在呈現階段所對的更改則會丟失。請參閱處理繼承的事件。
PreRender 事件

(OnPreRender 方法)

保存狀態
在此階段后,自動將控件的 ViewState 屬性保持到字符串對象中。此字符串對象被發送到客戶端并作為隱藏變量發送回來。為了提高效率,控件可以重寫 SaveViewState 方法以修改 ViewState 屬性。請參閱維護控件中的狀態。
SaveViewState 方法

呈現
生成呈現給客戶端的輸出。請參閱呈現 ASP.NET 服務器控件。
Render 方法

處置
執行銷毀控件前的所有最終清理操作。在此階段必須釋放對昂貴資源的引用,如數據庫鏈接。請參閱 ASP.NET 服務器控件中的方法。
Dispose 方法

卸載
執行銷毀控件前的所有最終清理操作。控件作者通常在 Dispose 中執行清除,而不處理此事件。
UnLoad 事件(On UnLoad 方法)

從這個表里面我們可以清楚的看到一個Page從裝載到卸載之間調用的方法和觸發的時間,接下來我們就深入的對其進行一些分析。

看了上面的表,細心的朋友可能要問了,既然OnInit是頁面生命周期的開始,而我們在上一講中談到控件在子類中被創建,那么在這里實際上在InitializeComponent方法中我們已經可以使用父類中聲名的字段了,那么就意味著子類的初始化更在這之前?

在第三個標題中我們講到了頁面類的ProcessRequest才是真正意義上的頁面聲明周期的開始,這個方法是由HttpApplication調用的(其中調用的方式比較復雜,有機會單獨撰文來講解),一個Page對請求的處理就是從這個方法開始,通過反編譯.Net類庫來查看源代碼,我們發現在System.Web.WebControls.Page的基類:System.Web.WebControls.TemplateControl(它是頁面和用戶控件的基類)中定義了一個“FrameworkInitialize”虛擬方法,然后在Page的ProcessRequest中最先調用了這個方法,在生成器生成的ASPX的源代碼中我們發現了這個方法的蹤影,所有的控件都在這個方法中被初始化,頁面的控件樹就在這個時候產生。

接下來的事情就簡單了,我們來逐步分析頁面生命周期的每一項:

1、 初始化

初始化對應Page的Init事件和OnInit方法。

如果要重寫,MSDN推薦的方式是重載OnInti方法,而不是增加一個Init事件的代理,這兩者是有差別的,前者可以控制調用父類OnInit方法的順序,而后者只能在父類的OnInit后執行(實際上是在OnInit里面被調用的)。

2、 加載視圖狀態

這是個比較重要的方法,我們知道,對于每次請求,實際上是由不同的頁面類實例來處理的,為了保證兩次請求間的狀態,ASP.Net使用了ViewState,關于ViewState的描述,請參考本人的另一篇文章:

http://expert.csdn.net/Expert/topic/1558/1558798.xml?temp=.2561609

LoadViewState方法就是從ViewState中獲取上一次的狀態,并依照頁面的控件樹的結構,用遞歸來遍歷整個樹,將對應的狀態恢復到每一個控件上。

3、 處理回發數據

這個方法是用來檢查客戶端發回的控件數據的狀態是否發生了改變。方法的原型:

public virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection)

postDataKey是標識控件的關鍵字(也就是postCollection中的Key),postCollection是包含回發數據的集合,我們可以重寫這個方法,然后檢查回發的數據是否發生了變化,如果是則返回一個True,“如果控件狀態因回發而更改,則 LoadPostData 返回 true;否則返回 false。頁框架跟蹤所有返回 true 的控件并在這些控件上調用 RaisePostDataChangedEvent。”(摘自MSDN)

這個方法是System.Web.WebControls.Control中定義的,也是所有需要處理事件的自定義控件需要處理的方法,對于我們今天討論的Page來說,可以不用管它。

4、 加載

加載對應Load事件和OnLoad方法,對于這個事件,相信大多數朋友都會比較熟悉,用VS.Net生成的頁面中的Page_Load方法就是響應Load事件的方法,對于每一次請求,Load事件都會觸發,Page_Load方法也就會執行,相信這也是大多數人了解ASP.Net的第一步。

Page_Load方法響應了Load事件,這個事件是在System.Web.WebControl.Control類中定義的(這個類是Page和所有服務器控件的祖宗),并且在OnLoad方法中被觸發。

很多人可能碰到過這樣的事情,寫了一個PageBase類,然后在Page_Load中來驗證用戶信息,結果發現不管驗證是否成功,子類頁面的Page_Load總是會先執行,這個時候很可能留下一些安全性的隱患,用戶可能在沒有得到驗證的情況下就執行了子類中的Page_Load方法。

出現這個問題的原因很簡單,因為Page_Load方法是在OnInit中被添加到Load事件中的,而子類的OnInit方法中是先添加了Load事件,然后再調用base.OnInit,這樣就造成了子類的Page_Load被先添加,那么先執行了。

要解決這個問題也很簡單,有兩種方法:

1) 在PageBase中重載OnLoad方法,然后在OnLoad中驗證用戶,然后調用base.OnLoad,因為Load事件是在OnLoad中觸發,這樣我們就可以保證在觸發Load事件之前驗證用戶。

2) 在子類的OnInit方法中先調用base.OnInit,這樣來保證父類先執行Page_Load

5、 發送回發更改通知

這個方法對應第3步的處理回發數據,如果處理回發數據返回True,頁面框架就會調用此方法來觸發數據更改的事件,所以自定義控件的回發數據更改事件需要在此方法中觸發。

同樣這個方法對于Page來說,沒有太大的用處,當然你也可以在Page的基礎上自己定義數據更改的事件,這當然也是可以的。

6、 處理回發事件

這個方法是大多數服務器控件事件引發的地方,當請求中包含控件事件觸發的信息時(服務器控件的事件是另一個論題,我會在不久將來另外撰文討論),頁面控件會調用相應控件的RaisePostBackEvent方法來引發服務器端的事件。

這里又引出一個常見的問題:

經常有網友問,為什么修改提交后的數據并沒有更改

多數的情況都是他們沒有理解服務器事件的觸發流程,我們可以看出,觸發服務器事件是在Page的Load之后,也就是說頁面會先執行Page_Load,然后才會執行按鈕(這里以按鈕為例)的點擊事件,很多朋友都是在Page_Load中綁定數據,然后在按鈕事件中處理更改,這樣做有一個毛病,Page_Load永遠都是在按鈕事件之前執行,那么意味著數據還沒來得及更改,Page_Load中的數據綁定的代碼就先執行了,原有的數據又賦給了控件,那么執行按鈕事件的時候,實際上獲得的是原有的數據,那么更新當然就沒有效果了。

更改這個問題也非常簡單,比較合理的做法是把數據綁定的代碼寫成一個方法,我們假設為BindData:

private void BindData()

{

//綁定數據

}

然后修改PageLoad:

private void Page_Load( object sender,EventArgs e )

{

if( !IsPostBack )

{

BindData(); //在頁面第一次訪問的時候綁定數據

}

}

最后在按鈕事件中:

private Button1_Click( object sender,EventArgs e )

{

//更新數據

BindData();//重新綁定數據

}

7、 預呈現

最終請求的處理都會轉變為發回服務器的響應,預呈現這個階段就是執行在最終呈現之前所作的狀態的更改,因為在呈現一個控件之前,我們必須根據它的屬性來產生Html,比如Style屬性,這是最典型的例子,在預呈現之前,我們可以更改一個控件的Style,當執行預呈現的時候,我們就可以把Style保存下來,作為呈現階段顯示Html的樣式信息。

8、 保存狀態

這個階段是針對加載狀態的,我們多次提到,請求之間是不同的實例在處理,所以我們需要把本次的頁面和控件的狀態保存起來,這個階段就是把狀態寫入ViewState的階段。

9、 呈現

到這里,實際上頁面對請求的處理基本就告一段落了,在Render方法中,會遞歸整個頁面的控件樹,依次調用Render方法,把對應的Html代碼寫入最終響應的流中。

10、處置

實際上就是Dispose方法,在這個階段會釋放占用的資源,例如數據庫連接。

11、卸載

最后,頁面會執行OnUnLoad方法觸發UnLoad事件,處理在頁面對象被銷毀之前的最后處理,實際上ASP.Net提供這個事件只是設計上的考慮,通常資源的釋放都會在Dispose方法中完成,所以這個方法也變成雞肋了。

我們簡單的介紹了頁面的生存周期,對于服務器端事件的處理做了不太深入的講解,今天主要是想大家了解頁面執行的周期,對于服務器控件的事件和生存期我會在后續在寫一些文章來探討。

這些內容是我在學習ASP.Net的時候對Page研究的一些心得,具體的細節沒有很詳細的探討,更多的內容請大家參考MSDN,但是我舉了一些初學者常犯的錯誤和出現錯誤的原因,希望可以給大家帶來啟發





主站蜘蛛池模板: 日韩欧美激情视频 | 午夜国产精品福利在线观看 | 手机看片福利日韩欧美看片 | 屁屁网站在线观看www | 特黄特黄的视频 | 天堂日本岛a | 日本一区二区高清免费不卡 | 欧美线人一区二区三区 | 亚洲国产欧美在线人成 | 亚洲色视频在线播放网站 | 色小说亚洲 | 中文字幕欧美日韩久久 | 午夜影院普通用户体验区 | 亚洲综合一 | 日韩欧美一区二区三区不卡 | 日韩欧美视频 | 天天舔天天射 | 亚洲va久久久噜噜噜久久天堂 | 啪在线视频 | 天天想夜夜操 | 色91视频 | 桃色网站入口 | 亚洲 欧美 自拍 卡通 综合 | 午夜涩涩| 天天躁日日躁狠狠躁黑人躁 | 热久久国产欧美一区二区精品 | 四虎在线网址 | 一级黄片一级毛片 | 中文字幕免费在线视频 | 中文字幕免费高清视频 | 日本在线观看一级高清片 | 欧美在线视频免费观看 | 一区二区三区福利视频 | 在线观看 亚洲 | 一区二区视频网 | 色综合天天综合中文网 | 五月婷婷久| 天天狠狠色噜噜 | 最新国产在线 | 欧美中文在线视频 | 夜鲁鲁鲁夜夜综合视频欧美 |