Page 類有一個 IsPostBack 屬性,這個屬性用來指示當前頁面是第一次加載還是響應了頁面上某個控件的服務器事件導致回發而加載。
1.asp.net頁面的聲明周期
asp.net頁面運行的時候將經歷一個聲明周期,這個生命周期中會進行一系列的操作,調用一系列的方法。了解asp.net頁面的生命周期對于精確控制頁面的控件呈現方式和行為非常重要。
一般說來一個常規頁面要經歷如下幾個生命周期階段:
階段 | 說明 |
頁請求 | 頁請求發生在頁生命周期開始之前。用戶請求頁時,ASP.NET 將確定是否需要分析和編譯頁(從而開始頁的生命周期),或者是否可以在不運行頁的情況下發送頁的緩存版本以進行響應。 |
開始 | 在開始階段,將設置頁屬性,如 Request 和 Response。在此階段,頁還將確定請求是回發請求還是新請求,并設置 IsPostBack 屬性。此外,在開始階段期間,還將設置頁的 UICulture 屬性。 |
頁初始化 | 頁初始化期間,可以使用頁中的控件,并將設置每個控件的 UniqueID 屬性。此外,任何主題都將應用于頁。如果當前請求是回發請求,則回發數據尚未加載,并且控件屬性值尚未還原為視圖狀態中的值。 |
加載 | 加載期間,如果當前請求是回發請求,則將使用從視圖狀態和控件狀態恢復的信息加載控件屬性。 |
驗證 | 在驗證期間,將調用所有驗證程序控件的 Validate 方法,此方法將設置各個驗證程序控件和頁的 IsValid 屬性。 |
回發事件處理 | 如果請求是回發請求,則將調用所有事件處理程序。 |
呈現 | 在呈現期間,視圖狀態將被保存到頁,然后頁將調用每個控件,以將其呈現的輸出提供給頁的 Response 屬性的 OutputStream。 |
卸載 | 完全呈現頁、將頁發送至客戶端并準備丟棄時,將調用卸載。此時,將卸載頁屬性(如 Response 和 Request)并執行清理。 |
在頁的生命周期中,一般會有如下事件:
頁事件 | 典型使用 |
Page_PReInit | 使用 IsPostBack 屬性確定是否是第一次處理該頁。 創建或重新創建動態控件。 動態設置主控頁。 動態設置 Theme 屬性。 讀取或設置配置文件屬性值。 注意:如果請求是回發請求,則控件的值尚未從視圖狀態還原。如果在此階段設置控件屬性,則其值可能會在下一階段被改寫。 |
Page_Init | 讀取或初始化控件屬性。 |
Page_Load | 讀取和更新控件屬性。 |
Control events | 執行特定于應用程序的處理: 如果頁包含驗證程序控件,請在執行任何處理之前檢查頁和各個驗證控件的 IsValid 屬性。 處理特定事件,如 Button 控件的 Click 事件。 |
Page_PreRender | 對頁的內容進行最后更改。 |
Page_Unload | 執行最后的清理工作,可能包括: 關閉打開的文件和數據庫連接。 完成日志記錄或其他特定于請求的任務。 |
需要注意的是,每個asp.net控件也有與asp.net類似的生命周期,如果aspx頁面中包含有asp.net服務器控件,那么在調用頁面的方法時也會調用控件的相關方法。
另外,Web應用程序是無狀態的。每次請求一個新網頁或者刷新頁面服務器都會創建一個當前頁的新實例,這就意味著無法獲取頁面的以前的信息,如果確實需要這么做,需要采用額外的機制。
Response.Write("<script language='Javascript'>alert('" + DateTime.Now.ToString() + "')</script>");
這樣每次運行Home.aspx頁面的時候都會彈出一個對話框。
輸出的javascript代碼在<html></html>標記之外。
在 Page類 中有一個 ClientScript 屬性,它是 ClientScriptManager 的實例,這個類是在 asp.net2.0 中新增的。ClientScriptManager有如下幾個常用方法:
RegisterClientScriptBlock方法:向 Page 對象注冊客戶端腳本。
RegisterStartupScript方法:向 Page 對象注冊啟動腳本。
ClientScriptManager類通過鍵string和Type來唯一標識腳本。具有相同類型的鍵和Type的腳本識為同一腳本。
if (!ClientScript.IsClientScriptBlockRegistered(this.GetType(), "ClientScriptBlock")) { ClientScript.RegisterClientScriptBlock(this.GetType(), "ClientScriptBlock", "<script language='javascript'>alert('ClientScriptBlock')</script>"); }if (!ClientScript.IsStartupScriptRegistered(this.GetType(), "StartupScript")) { ClientScript.RegisterStartupScript(this.GetType(), "StartupScript", "<script language='javascript'>alert('StartupScript')</script>"); }
執行該頁面時,會彈出兩個提示窗口
上面的兩個方法輸出的javascript腳本都在<form></form>標記之內,不會破環文章的結構,而且RegisterClientScriptBlock方法輸出的javascript腳本代碼塊靠近<form>標記的開始標記,而RegisterStartupScript方法輸出的javascript腳本代碼塊靠近<form>標記的結束標記,了解這一點對于控制動態添加的客戶端腳本的時間是非常有利的。
3.回調技術(CallBack)
在asp.net中客戶端與服務器端的交互默認都是整頁面提交,此時客戶端將當前頁面表單中的數據(包括一些自動生成的隱藏域)都提交到服務器端,服務器重新實例化一個當前頁面類的實例響應這個請求,然后將整個頁面的內容重新發送到客戶端,這種處理方式對運行結果沒什么影響,不過這種方式加重了網絡的數據傳輸負擔、加大了服務器的工作壓力,并且用戶還需要等待最終處理結果。假如是我們希望有這么一個功能,當用戶填寫完用戶名之后就檢查服務器數據庫里是否已存在該用戶名,如果存在就給出已經存在此用戶名的提示,如果不存在就提示用戶此用戶名可用,對于這種情況其實只需要傳遞一個用戶名作為參數即可,上面的做法卻需要提交整個表單,有點小題大做。解決上面的問題的辦法目前主流做法有三種:純javascript實現、微軟Ajax類庫實現還有用AjaxPro實現。
這里我講另外一種實現:通過回調技術。
創建實現回調技術的網頁與普通asp.net網頁類似,只不過還需要做以下特殊工作:
(1)讓當前頁面實現ICallbackEventHandler接口,這個接口定義了兩個方法:string GetCallbackResult ()方法和void RaiseCallbackEvent (string eventArgument)方法。其中GetCallbackResult ()方法的作用是返回以控件為目標的回調事件的結果,RaiseCallbackEvent()方法的作用是處理以控件為目標的回調事件。
(2)為當前頁提供三個javascript客戶端腳本函數。一個javascript函數用于執行對服務器的實際請求,在這個函數中可以提供一個字符串類型的參數發送到服務器端;另一個javascript函數用于接收服務器端方法的執行后返回的字符串類型結果,并處理這個結果;還有一個是執行對服務器請求的幫助函數,在服務器代碼中通過GetCallbackEventReference()方法獲取這個方法的引用時由asp.net自動生成這個函數。
下面我以一個詳細的例子來講述如何使用回調,用Dreamweaver創建一個Register. aspx頁面,代碼如下:
<%@ Page Language="C#" ContentType="text/html" ResponseEncoding="gb2312" %><%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %><%@ Import Namespace="System.Text" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=gb2312" /><title>用戶注冊</title><script language="javascript">//客戶端執行的方法//下面的方法是接收并處理服務器方法執行的返回結果function Success(args, context){ message.innerText = args;}//下面的方式是當接收服務器方法處理的結果發生異常時調用的方法function Error(args, context){ message.innerText = '發生了異常';}</script><script language="c#" runat="server">string result="";// 定義在服務器端運行的回調方法.public void RaiseCallbackEvent(String eventArgument){ if(eventArgument.ToLower().IndexOf("admin")!=-1) { result=eventArgument+"不能作為用戶名注冊。"; } else { result=eventArgument+"可以注冊。"; } //throw new Exception();}//定義返回回調方法執行結果的方法public string GetCallbackResult(){ return result;}//服務器上執行的方法public void Page_Load(Object sender,EventArgs e){ // 獲取當前頁的ClientScriptManager的引用 ClientScriptManager csm = Page.ClientScript; // 獲取回調引用。會在客戶端生成WebForm_DoCallback方法,調用它來達到異步調用。這個方式是微軟寫的方法,會被發送到客戶端 //注意這里的"Success"和"Error"兩個字符串分別客戶端代碼中定義的兩個javascript函數 //下面的方法最后一個參數的意義:true表示執行異步回調,false表示執行同步回調 String reference = csm.GetCallbackEventReference(this, "args","Success","","Error",false); String callbackScript = "function CallServerMethod(args, context) {/n" + reference + ";/n }"; // 向當前頁面注冊javascript腳本代碼 csm.RegisterClientScriptBlock(this.GetType(), "CallServerMethod", callbackScript, true);}</script></head><body><form id="form1" runat="server"><table border="1" cellpadding="0" cellspacing="0" width="400px"><tr><td width="100px">用戶名</td><td><input type="text" size="10" maxlength="20" id="txtUserName" onblur="CallServerMethod(txtUserName.value,null)" />
<span id="message"></span></td></tr><tr><td>密碼</td><td><input type="passWord" size="10" maxlength="20" id="txtPwd" /></td></tr></table></form></body>
上面的頁面中已經添加了足夠詳盡的注視,不過還是要說明幾點:
[1]
<%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>
這句表示當前頁面實現了ICallbackEventHandler接口,如果采用頁面與代碼分離的模式,后臺cs代碼則應是:
public partial class Register : System.Web.UI.Page, ICallbackEventHandler{//cs代碼 }
[2]
<input type="text" size="10" maxlength="20" id="txtUserName" onblur="CallServerMethod(txtUserName.value,null)" />
這里有一個onblur="CallServerMethod(txtUserName.value,null),表示當用戶名文本框失去焦點之后激發CallServerMethod這個客戶端方法,這個客戶端方法是由asp.net動態生成的。
[3]
csm.GetCallbackEventReference(this, "args","Success","","Error",false);
中的"Success"和"Error"分別代表客戶端的javascript函數,可以在代碼中見到,其中"Success"代表調用服務器端方法成功后要執行的客戶端方法名,"Error"代表調用服務器端方法失敗時調用的客戶端方法名。
來源:http://zhoufoxcn.blog.51cto.com/792419/166784
新聞熱點
疑難解答