明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

ASP.NET Web Page應(yīng)用深入探討

[摘要]一、服務(wù)器腳本基礎(chǔ)介紹   首先,我們先復(fù)習(xí)一下Web服務(wù)器頁面的基本執(zhí)行方式:   1、客戶端通過在瀏覽器的地址欄敲入地址來發(fā)送請求到服務(wù)器端  2、服務(wù)器接收到請求之后,發(fā)給相應(yīng)的服務(wù)器端頁面(也就是腳本)來執(zhí)行,腳本產(chǎn)生客戶端的響應(yīng),發(fā)送回客戶端  3、客戶端瀏覽器接收到服務(wù)器傳回的響應(yīng),對...

  一、服務(wù)器腳本基礎(chǔ)介紹

  首先,我們先復(fù)習(xí)一下Web服務(wù)器頁面的基本執(zhí)行方式:

  1、客戶端通過在瀏覽器的地址欄敲入地址來發(fā)送請求到服務(wù)器端

  2、服務(wù)器接收到請求之后,發(fā)給相應(yīng)的服務(wù)器端頁面(也就是腳本)來執(zhí)行,腳本產(chǎn)生客戶端的響應(yīng),發(fā)送回客戶端

  3、客戶端瀏覽器接收到服務(wù)器傳回的響應(yīng),對Html進(jìn)行解析,將圖形化的網(wǎng)頁呈現(xiàn)在用戶面前

  對于服務(wù)器和客戶端的交互,通常通過下面幾種主要方式:

  1、Form:這是最主要的方式,標(biāo)準(zhǔn)化的控件來獲取用戶的輸入,F(xiàn)orm的提交將數(shù)據(jù)發(fā)送給服務(wù)器端處理

  2、QueryString:通過在Url后面帶參數(shù)達(dá)到將參數(shù)傳送給服務(wù)器,這種方式其實(shí)跟Get方式的Form是一樣的

  3、Cookies:這是一種比較特殊的方式,通常用于用戶身份的確認(rèn)

  二、ASP.Net簡介

  傳統(tǒng)的服務(wù)器腳本語言,如ASP、JSP等,編寫服務(wù)器腳本的方式大同小異,都是在Html中嵌入解釋或編譯執(zhí)行的代碼,由服務(wù)器平臺(tái)執(zhí)行這些代碼來生成Html;對于這類似的腳本,頁面的生存周期實(shí)際上很簡單,就是從開頭至末尾,執(zhí)行完所有的代碼,當(dāng)然用Java編寫的Servlet可以編寫更復(fù)雜的代碼,但是從結(jié)構(gòu)上看,和JSP沒什么區(qū)別。

  ASP.Net的出現(xiàn),打破了這種傳統(tǒng);ASP.Net采用了CodeBehind技術(shù)和服務(wù)器端控件,加入了服務(wù)器端的事件的概念,改變了腳本語言編寫的模式,更加貼近Window編程,使Web編程更加簡單、直觀;但是我們要看到,ASP.Net本身并沒有改變Web編程的基本模式,只是封裝了一些細(xì)節(jié)、提供了一些易用的功能,使代碼更容易編寫和維護(hù);從某種程度上來說,將服務(wù)器端執(zhí)行的方式復(fù)雜化了,這就是我們今天要討論的主體:ASP.Net Web Page的生存周期。

  三、ASP.Net請求處理模式

  我們說,ASP.Net的Web Page并沒有脫離Web編程的模式,所以它仍然是以 請求->接收請求->處理請求->發(fā)送響應(yīng) 這樣的模式在工作,每一次與客戶端的交互都會(huì)引發(fā)一次新的請求,所以一個(gè)Web Page的生命周期是以一次請求為基礎(chǔ)的。

  當(dāng)IIS收到客戶端的請求的時(shí)候,會(huì)將請求交給aspnet_wp這個(gè)進(jìn)程來處理,這個(gè)進(jìn)程會(huì)查看請求的應(yīng)用程序域是否存在,如果不存在則會(huì)創(chuàng)建一個(gè),然后會(huì)創(chuàng)建一個(gè)Http運(yùn)行時(shí)(HttpRuntime)來處理請求,這個(gè)運(yùn)行時(shí)“為當(dāng)前應(yīng)用程序提供一組 ASP.NET 運(yùn)行時(shí)服務(wù)”(摘自MSDN)。

  HttpRuntime在處理請求的時(shí)候,會(huì)維護(hù)一系列的應(yīng)用程序?qū)嵗,也就是?yīng)用程序的Global類(global.asax)的實(shí)例,這些實(shí)例在沒有請求的時(shí)候,會(huì)存放在一個(gè)應(yīng)用程序池中(實(shí)際上應(yīng)用程序池由另一個(gè)類來維護(hù),HttpRuntime只是簡單的調(diào)用),每接收到一個(gè)請求,HttpRuntime都會(huì)獲取一個(gè)閑置的實(shí)例來處理請求,這個(gè)實(shí)例在請求結(jié)束前不會(huì)處理其他的請求,處理完畢之后,它又會(huì)回到池中,“一個(gè)實(shí)例在其生存期內(nèi)被用于處理多個(gè)請求,但它一次只能處理一個(gè)請求!保ㄕ訫SDN)

  當(dāng)應(yīng)用程序?qū)嵗幚碚埱蟮臅r(shí)候,它會(huì)創(chuàng)建請求頁面類的實(shí)例,執(zhí)行它的ProcessRequest方法來處理請求,這個(gè)方法也就是Web Page生命周期的開始。

  四、Aspx頁面與CodeBehind

  在深入了解頁面的生命周期之前,我們先來探討一些Aspx與CodeBehind之間的關(guān)系。

<%@ Page language="c#" Codebehind="WebForm.aspx.cs" Inherits="MyNamespace.WebForm" %>

  相信使用過CodeBehind技術(shù)的朋友,對ASPX頂部的這句話應(yīng)該是非常熟悉了,我們來一項(xiàng)一項(xiàng)的分析它:

  Page language="c#" 這個(gè)就不用多說了吧

  Codebehind="WebForm.aspx.cs" 這一句表示綁定的代碼文件

  Inherits="MyNamespace.WebForm" 這句非常重要,它表示頁面繼承的類名稱,也就是CodeBehind的代碼文件中的類,這個(gè)類必須從System.Web.WebControls.Page派生

  從上面我們可以分析出,實(shí)際上CodeBehind中的類就是頁面(ASPX)的基類,到這里,可能有些朋友要問了,在編寫ASPX的時(shí)候,完全是按照ASP的方式,在Html中嵌入代碼或者嵌入服務(wù)器控件,沒有看到所謂“類”的影子。

  這個(gè)問題實(shí)際上并不復(fù)雜,各位使用ASP.Net編程的朋友可以到你們的系統(tǒng)盤:\WINDOWS\Microsoft.NET\Framework\<版本號>\Temporary ASP.NET Files這個(gè)目錄下,這個(gè)下面就放了所有本機(jī)上存在的ASP.Net應(yīng)用程序的臨時(shí)文件,子目錄的名稱就是應(yīng)用程序的名稱,然后再下去兩層(為了保證唯一,ASP.Net自動(dòng)產(chǎn)生了兩層子目錄,并且子目錄名稱是隨機(jī)的),然后我們會(huì)發(fā)現(xiàn)有很多類似:“yfy1gjhc.dll”、“xeunj5u3.dll”這樣的鏈接庫以及“komee-bp.0.cs”、“9falckav.0.cs”這樣的源文件,實(shí)際上這就是ASPX被ASP.Net動(dòng)態(tài)編譯后的結(jié)果,打開這些源文件我們可以發(fā)現(xiàn):

public class WebForm_aspx : MyNamespace.WebForm, System.Web.SessionState.IRequiresSessionState

  這就印證了我們前面的說法,ASPX是代碼綁定類的子類,它的名稱是ASPX文件名加上“_aspx”后綴,通過研究這些代碼我們可以發(fā)現(xiàn),實(shí)際上所有aspx中定義的服務(wù)器控件都是在這些代碼中生成的,然后動(dòng)態(tài)產(chǎn)生這些代碼的時(shí)候,把原來在ASPX中嵌入的代碼寫在了相應(yīng)的位置。

  當(dāng)某個(gè)頁面第一次被訪問的時(shí)候,Http運(yùn)行時(shí)就會(huì)使用一個(gè)代碼生成器去解析ASPX文件并生成源代碼并編譯,然后以后的訪問就直接調(diào)用編譯后的dll,這也是為什么ASPX第一次訪問的時(shí)候非常慢的原因。

  解釋了這個(gè)問題,我們再來看另一個(gè)問題。我們在使用代碼綁定的時(shí)候,在設(shè)計(jì)頁面拖一個(gè)控件,然后切換到代碼視圖,就可以直接在Page_Load中使用這個(gè)控件了,既然控件是在子類中產(chǎn)生的,那為什么在父類中可以直接使用呢?

  實(shí)際上我們可以發(fā)現(xiàn),每當(dāng)用VS.Net拖一個(gè)控件到頁面上,代碼綁定文件中總是會(huì)類似這樣的添加一個(gè)聲明:

protected System.Web.WebControls.Button Button1;

  我們可以發(fā)現(xiàn)這個(gè)字段被聲明成protected,而且名字與ASPX中控件的ID一致,仔細(xì)想一想,這個(gè)問題就迎刃而解了。我們前面提到ASPX的源代碼是被生成器動(dòng)態(tài)生成和編譯的,生成器會(huì)產(chǎn)生動(dòng)態(tài)生成每一個(gè)服務(wù)器控件的代碼,在生成的時(shí)候,它會(huì)檢查父類有沒有聲明這個(gè)控件,如果聲明了,它會(huì)添加類似下面的一句代碼:

this.DataGrid1 = __ctrl;

  這個(gè)__ctrl就是生成該控件的變量,這時(shí)候它就把控件的引用賦給了父類中相應(yīng)的變量,這也是為什么父類中的聲明必須為protected(實(shí)際上也可以為public),因?yàn)橐WC子類能夠調(diào)用。

  然后在執(zhí)行Page_Load的時(shí)候,因?yàn)檫@時(shí)候父類的聲明已經(jīng)被子類中的初始化代碼賦了值,所以我們就可以使用這個(gè)字段來訪問對應(yīng)的控件,了解了這些,我們就不會(huì)犯在代碼綁定文件中的構(gòu)造器里使用控件,造成空引用的異常的錯(cuò)誤了,因?yàn)闃?gòu)造器是最先執(zhí)行的,這時(shí)候子類的初始化還沒有開始,所以父類中的字段是空值,至于子類是什么時(shí)候初始化我們放到后面討論。

  五、頁面生存周期

  現(xiàn)在回到第三個(gè)標(biāo)題中講到的內(nèi)容,我們講到了HttpApplication的實(shí)例接收請求,并創(chuàng)建頁面類的實(shí)例,實(shí)際上這個(gè)實(shí)例也就是動(dòng)態(tài)編譯的ASPX的類的一個(gè)實(shí)例,上一個(gè)標(biāo)題中我們了解到ASPX實(shí)際上是代碼綁定中類的子類,所以它繼承了所有的protected方法。

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

#region Web Form Designer generated code

override protected void OnInit(EventArgs e)
{
 //
 // CODEGEN:該調(diào)用是 ASP.NET Web 窗體設(shè)計(jì)器所必需的。
 //
 InitializeComponent();
 base.OnInit(e);
}

/// <summary>
/// 設(shè)計(jì)器支持所需的方法 - 不要使用代碼編輯器修改
/// 此方法的內(nèi)容。
/// </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

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

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

  “每次請求 ASP.NET 頁時(shí),服務(wù)器就會(huì)加載一個(gè) ASP.NET 頁,并在請求完成時(shí)卸載該頁。頁及其包含的服務(wù)器控件負(fù)責(zé)執(zhí)行請求并將 HTML 呈現(xiàn)給客戶端。雖然客戶端和服務(wù)器之間的通訊是無狀態(tài)的和斷續(xù)的,但是必須使客戶感覺到這是一個(gè)連續(xù)執(zhí)行的過程!

  “這種連續(xù)性假象是由 ASP.NET 頁框架、頁及其控件實(shí)現(xiàn)的;匕l(fā)后,控件的行為必須看起來是從上次 Web 請求結(jié)束的地方開始的。雖然 ASP.NET 頁框架可使執(zhí)行狀態(tài)管理相對容易一些,但是為了獲得連續(xù)性效果,控件開發(fā)人員必須知道控件的執(zhí)行順序?丶_發(fā)人員需要了解:在控件生命周期的各個(gè)階段,控件可使用哪些信息、保持哪些數(shù)據(jù)、控件呈現(xiàn)時(shí)處于哪種狀態(tài)。例如,在填充頁上的控件樹之前控件不能調(diào)用其父級! “下表提供了控件生命周期中各階段的高級概述。有關(guān)詳細(xì)信息,請點(diǎn)擊表中的鏈接!

階段控件需要執(zhí)行的操作要重寫的方法或事件
初始化初始化在傳入 Web 請求生命周期內(nèi)所需的設(shè)置。請參閱處理繼承的事件。Init 事件(OnInit 方法)
加載視圖狀態(tài)在此階段結(jié)束時(shí),就會(huì)自動(dòng)填充控件的 ViewState 屬性,詳見維護(hù)控件中的狀態(tài)中的介紹?丶梢灾貙 LoadViewState 方法的默認(rèn)實(shí)現(xiàn),以自定義狀態(tài)還原。LoadViewState 方法
處理回發(fā)數(shù)據(jù)處理傳入窗體數(shù)據(jù),并相應(yīng)地更新屬性。請參閱處理回發(fā)數(shù)據(jù)。
注意 只有處理回發(fā)數(shù)據(jù)的控件參與此階段。
LoadPostData 方法 (如果已實(shí)現(xiàn)IPostBackDataHandler)
加載執(zhí)行所有請求共有的操作,如設(shè)置數(shù)據(jù)庫查詢。此時(shí),樹中的服務(wù)器控件已創(chuàng)建并初始化、狀態(tài)已還原并且窗體控件反映了客戶端的數(shù)據(jù)。請參閱處理繼承的事件。Load 事件
(OnLoad 方法)
發(fā)送回發(fā)更改通知引發(fā)更改事件以響應(yīng)當(dāng)前和以前回發(fā)之間的狀態(tài)更改。請參閱處理回發(fā)數(shù)據(jù)。

注意 只有引發(fā)回發(fā)更改事件的控件參與此階段。
RaisePostDataChangedEvent 方法
(如果已實(shí)現(xiàn) IPostBackDataHandler)
處理回發(fā)事件處理引起回發(fā)的客戶端事件,并在服務(wù)器上引發(fā)相應(yīng)的事件。請參閱捕獲回發(fā)事件。

注意 只有處理回發(fā)事件的控件參與此階段。
RaisePostBackEvent 方法
(如果已實(shí)現(xiàn) IPostBackEventHandler)
預(yù)呈現(xiàn)在呈現(xiàn)輸出之前執(zhí)行任何更新?梢员4嬖陬A(yù)呈現(xiàn)階段對控件狀態(tài)所做的更改,而在呈現(xiàn)階段所對的更改則會(huì)丟失。請參閱處理繼承的事件。PreRender 事件
(OnPreRender 方法)
保存狀態(tài)在此階段后,自動(dòng)將控件的 ViewState 屬性保持到字符串對象中。此字符串對象被發(fā)送到客戶端并作為隱藏變量發(fā)送回來。為了提高效率,控件可以重寫 SaveViewState 方法以修改 ViewState 屬性。請參閱維護(hù)控件中的狀態(tài)。SaveViewState 方法
呈現(xiàn)生成呈現(xiàn)給客戶端的輸出。請參閱呈現(xiàn) ASP.NET 服務(wù)器控件。Render 方法
處置執(zhí)行銷毀控件前的所有最終清理操作。在此階段必須釋放對昂貴資源的引用,如數(shù)據(jù)庫鏈接。請參閱 ASP.NET 服務(wù)器控件中的方法。
Dispose 方法
卸載執(zhí)行銷毀控件前的所有最終清理操作?丶髡咄ǔT Dispose 中執(zhí)行清除,而不處理此事件。 UnLoad 事件(On UnLoad 方法)

  從這個(gè)表里面我們可以清楚的看到一個(gè)Page從裝載到卸載之間調(diào)用的方法和觸發(fā)的時(shí)間,接下來我們就深入的對其進(jìn)行一些分析。

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

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

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

  1、初始化

  初始化對應(yīng)Page的Init事件和OnInit方法。

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

  2、 加載視圖狀態(tài)

  這是個(gè)比較重要的方法,我們知道,對于每次請求,實(shí)際上是由不同的頁面類實(shí)例來處理的,為了保證兩次請求間的狀態(tài),ASP.Net使用了ViewState。

  LoadViewState方法就是從ViewState中獲取上一次的狀態(tài),并依照頁面的控件樹的結(jié)構(gòu),用遞歸來遍歷整個(gè)樹,將對應(yīng)的狀態(tài)恢復(fù)到每一個(gè)控件上。

  3、 處理回發(fā)數(shù)據(jù)

  這個(gè)方法是用來檢查客戶端發(fā)回的控件數(shù)據(jù)的狀態(tài)是否發(fā)生了改變。方法的原型:

public virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection)

  postDataKey是標(biāo)識控件的關(guān)鍵字(也就是postCollection中的Key),postCollection是包含回發(fā)數(shù)據(jù)的集合,我們可以重寫這個(gè)方法,然后檢查回發(fā)的數(shù)據(jù)是否發(fā)生了變化,如果是則返回一個(gè)True,“如果控件狀態(tài)因回發(fā)而更改,則 LoadPostData 返回 true;否則返回 false。頁框架跟蹤所有返回 true 的控件并在這些控件上調(diào)用 RaisePostDataChangedEvent!保ㄕ訫SDN)

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

  4、 加載

  加載對應(yīng)Load事件和OnLoad方法,對于這個(gè)事件,相信大多數(shù)朋友都會(huì)比較熟悉,用VS.Net生成的頁面中的Page_Load方法就是響應(yīng)Load事件的方法,對于每一次請求,Load事件都會(huì)觸發(fā),Page_Load方法也就會(huì)執(zhí)行,相信這也是大多數(shù)人了解ASP.Net的第一步。

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

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

  出現(xiàn)這個(gè)問題的原因很簡單,因?yàn)镻age_Load方法是在OnInit中被添加到Load事件中的,而子類的OnInit方法中是先添加了Load事件,然后再調(diào)用base.OnInit,這樣就造成了子類的Page_Load被先添加,那么先執(zhí)行了。

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

  1) 在PageBase中重載OnLoad方法,然后在OnLoad中驗(yàn)證用戶,然后調(diào)用base.OnLoad,因?yàn)長oad事件是在OnLoad中觸發(fā),這樣我們就可以保證在觸發(fā)Load事件之前驗(yàn)證用戶。

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

  5、 發(fā)送回發(fā)更改通知

  這個(gè)方法對應(yīng)第3步的處理回發(fā)數(shù)據(jù),如果處理回發(fā)數(shù)據(jù)返回True,頁面框架就會(huì)調(diào)用此方法來觸發(fā)數(shù)據(jù)更改的事件,所以自定義控件的回發(fā)數(shù)據(jù)更改事件需要在此方法中觸發(fā)。

  同樣這個(gè)方法對于Page來說,沒有太大的用處,當(dāng)然你也可以在Page的基礎(chǔ)上自己定義數(shù)據(jù)更改的事件,這當(dāng)然也是可以的。

  6、 處理回發(fā)事件

  這個(gè)方法是大多數(shù)服務(wù)器控件事件引發(fā)的地方,當(dāng)請求中包含控件事件觸發(fā)的信息時(shí)(服務(wù)器控件的事件是另一個(gè)論題,我會(huì)在不久將來另外撰文討論),頁面控件會(huì)調(diào)用相應(yīng)控件的RaisePostBackEvent方法來引發(fā)服務(wù)器端的事件。

  這里又引出一個(gè)常見的問題:

  經(jīng)常有網(wǎng)友問,為什么修改提交后的數(shù)據(jù)并沒有更改

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

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

private void BindData()
{
 //綁定數(shù)據(jù)
}

  然后修改PageLoad:

private void Page_Load( object sender,EventArgs e )
{
 if( !IsPostBack )
 {
  BindData(); //在頁面第一次訪問的時(shí)候綁定數(shù)據(jù)
 }
}

  最后在按鈕事件中:

private Button1_Click( object sender,EventArgs e )
{
 //更新數(shù)據(jù)
 BindData();//重新綁定數(shù)據(jù)
}

  7、預(yù)呈現(xiàn)

  最終請求的處理都會(huì)轉(zhuǎn)變?yōu)榘l(fā)回服務(wù)器的響應(yīng),預(yù)呈現(xiàn)這個(gè)階段就是執(zhí)行在最終呈現(xiàn)之前所作的狀態(tài)的更改,因?yàn)樵诔尸F(xiàn)一個(gè)控件之前,我們必須根據(jù)它的屬性來產(chǎn)生Html,比如Style屬性,這是最典型的例子,在預(yù)呈現(xiàn)之前,我們可以更改一個(gè)控件的Style,當(dāng)執(zhí)行預(yù)呈現(xiàn)的時(shí)候,我們就可以把Style保存下來,作為呈現(xiàn)階段顯示Html的樣式信息。

  8、保存狀態(tài)

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

  9、呈現(xiàn)

  到這里,實(shí)際上頁面對請求的處理基本就告一段落了,在Render方法中,會(huì)遞歸整個(gè)頁面的控件樹,依次調(diào)用Render方法,把對應(yīng)的Html代碼寫入最終響應(yīng)的流中。

  10、處置

  實(shí)際上就是Dispose方法,在這個(gè)階段會(huì)釋放占用的資源,例如數(shù)據(jù)庫連接。

  11、卸載

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

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

  這些內(nèi)容是我在學(xué)習(xí)ASP.Net的時(shí)候?qū)age研究的一些心得,具體的細(xì)節(jié)沒有很詳細(xì)的探討,更多的內(nèi)容請大家參考MSDN,但是我舉了一些初學(xué)者常犯的錯(cuò)誤和出現(xiàn)錯(cuò)誤的原因,希望可以給大家?guī)韱l(fā)。