日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

asp.net夜话之五:Page类和回调技术

發布時間:2025/6/15 asp.net 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 asp.net夜话之五:Page类和回调技术 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

asp.net夜話之五:Page類和回調技術

在今天我主要要介紹的有如下知識點:
Page類介紹
Page的生命周期
IsPostBack屬性
ClientScriptManager類
回調技術(CallBack)

?

Page類介紹


asp.net有時候也被成為WebForm,因為開發一個asp.net頁面就像開發一個WinFrom窗體一樣,我們同樣可以采用拖拽控件、雙擊產生相關處理代碼的方法。在asp.net中,創建一個頁面可以采用兩種模型。


單頁模型
用Dreamweaver創建的asp.net頁面就是單頁模型,當然利用Visual Studio 2005也能創建單頁模型,不過在Visual Studio 2005中創建的頁面默認不是單頁模型,要想在Visual Studio 2005創建單頁模型的網頁如下:

?

?

項處于未選中狀態,默認情況下這個選項是處于選中狀態的。這樣就創建了單頁模型的網頁。
此時的頁面代碼如下:

?

?

注意在頁面中有這樣一句代碼:

  • <script?runat="server">
  • </script>
  • 這句代碼與普通javascript語句塊不同的是有一個runat="server"屬性,表示這里的代碼是在服務器上運行的C#代碼。切換到設計視圖,然后雙擊頁面,然后這部分會變成如下的樣子:

    ?

  • <script?runat="server">
  • ????protected?void?Page_Load(object?sender,?EventArgs?e)
  • ????{
  • ????}
  • </script>
  • 其中Page_Load就是頁面加載的時候在服務器上運行的方法。
    單頁模型的特點是HTML標記、控件代碼及服務器端運行的C#代碼全部包含在一個aspx頁面中,Web服務器第一次運行該頁面的時候會將這個頁面生成一個類文件,對于上面的Index.aspx頁面,會生成ASP.Index_aspx的類,然后再將這個ASP.Index_aspx類編譯成IL代碼,Web服務器通過CLR(Common Language Runtime,通用語言運行環境)運行相應的IL代碼。
    單頁模型的缺點是頁面和代碼混在一起,維護起來較為麻煩。

    ?

    代碼頁面分離模式
    代碼頁面模式就是將頁的標記(HTML代碼)和服務器端元素放在.aspx頁面中,而也代碼在位于一個.aspx.cs中。采用默認方式創建的aspx網頁就是這種方式。
    下面就是一個采用代碼頁面分離模式創建的Home.aspx頁面的代碼:

    ?

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Home.aspx.cs" Inherits="Home" %> <!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 runat="server"> <title>無標題頁</title> </head> <body> <form id="form1" runat="server"> <div> </div> </form> </body> </html>

    ?其對應的頁代碼是:

    ?

    using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; public partial class Home : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } }

    ?

    首先要關注的aspx的頭部分代碼:

    ?

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Home.aspx.cs" Inherits="Home" %>

    ?

    @Page是一個頁面指令,在這里Language="C#"指明了當前頁面采用的后臺代碼是C#語言,CodeFile="Home.aspx.cs"表示這個頁面對應的頁代碼文件是Home.aspx.cs這個文件,Inherits="Home"表示當前aspx頁繼承自Home這個類。


    現在再關注一下頁代碼文件聲明:

    public?partial?class?Home?:?System.Web.UI.Page

    ?

    從這部分代碼可以看出Home類是繼承自System.Web.UI.Page類的。注意這里還有一個C#2.0的關鍵字partial,這個關鍵字表示當前代碼是一個局部類,以表示這個類是構成整個Web頁面窗體的一部分。Web服務器運行這個頁面的時候最終會將aspx頁面和對應的頁代碼編譯成一個類文件,然后生成IL代碼。


    代碼頁面分離模式的好處是頁面展示部分和邏輯控制部分的代碼分離開來,便于管理和維護,這也是微軟推薦的開發方式。

    ?

    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應用程序是無狀態的。每次請求一個新網頁或者刷新頁面服務器都會創建一個當前頁的新實例,這就意味著無法獲取頁面的以前的信息,如果確實需要這么做,需要采用額外的機制。
    我們將剛才新建的Index.aspx頁面中添加代碼,如下:

    ?

    <%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> string date; protected void Page_Load(object sender, EventArgs e) { if (date == null)//如果date為空則設置為當前時間的字符串形式 { date = DateTime.Now.ToString(); } Response.Write("當前時間:"+date); } </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>無標題頁</title> </head> <body> <form id="form1" runat="server"> <div> </div> </form> </body> </html>

    ??

    ???? 按照正常理解,第一次運行的時候date字符串為null,會被設置成系統當前的字符串表示形式,并且輸出,再次刷新的時候date字符串不再為空,會依然輸出剛才的時間字符串,但是結果卻不是這樣。第一次運行的結果:

    ?

    刷新頁面之后的結果:

    ?

    ?

    這就證明了即使是刷新當前頁也會重新生成一個當前頁面的實例,因為只有在生成頁面新實例的情況下date字符串變量才為空,才會被重新設置值。

    ?

    IsPostBack屬性
    Page類有一個IsPostBack屬性,這個屬性用來指示當前頁面是第一次加載還是響應了頁面上某個控件的服務器事件導致回發而加載。
    這次我們繼續對Index.aspx頁面添加代碼,在頁面中增加了一個Button控件,如下:

    ?

    <%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> string date; protected void Page_Load(object sender, EventArgs e) { if (date == null)//如果date為空則設置為當前時間的字符串形式 { date = DateTime.Now.ToString(); } Response.Write("當前時間:"+date); if (!Page.IsPostBack) { Response.Write("第一次加載。"); } else { Response.Write("響應客戶端回發而加載。"); } } protected void btnOK_Click(object sender, EventArgs e) { } </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>無標題頁</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Button ID="btnOK" runat="server" OnClick="btnOK_Click" Text="提交" /></div> </form> </body> </html>

    ?

    ?

    頁面第一次運行的結果:

    ?

    按一下F5刷新頁面的結果:

    ?

    ?

    點擊一下“提交”按鈕之后的結果:

    ?

    ?

    ?

    由此可見每次打開一個頁面和刷新一個頁面效果都是一樣的,只有響應客戶端回發時IsPostBack屬性才是true。了解這個屬性和服務器采用了一種機制來“記錄”服務器控件的狀態這種做法(其實利用了ViewState和ControlState機制,這部分后續文章中會講到)對于將來數據綁定會有很大作用。

    ?

    ?

    動態輸出javascript腳本
    對于Index.aspx頁面上面的執行情況,我們看到了滿意的結果。我們再來看一下這個頁面在客戶端生成的HTML代碼,在瀏覽器窗口打開的頁面點鼠標右鍵,然后選擇“查看源文件”,HTML代碼如下:

    ?

    當前時間:2008-9-21 0:04:33響應客戶端回發而加載。 <!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><title> 無標題頁 </title></head> <body> <form name="form1" method="post" action="Index.aspx" id="form1"> <div> <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTY3NzE5MjIyMGRkD2VvJFADDdEHh4W9UfAyzIvI3ss=" /> </div> <div> <input type="submit" name="btnOK" value="提交" id="btnOK" /></div> <div> <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWAgL8vZamCQLdkpmPAeM33vfm1ARVNKdKAoq5+eQdFI1J" /> </div></form> </body> </html>

    ?

    ?

    我們會看到“當前時間:2008-9-21 0:04:33響應客戶端回發而加載。”這句話位于<html></html>標記之外。在第一夜時候就提到過,asp.net頁面是滿足XML標準的HTML語言,但是通過在Page_Load事件中利用Response屬性會將文字輸出在<html></html>標記之外,不符合XHTML標準。這對于普通頁面來說也許并無大礙,但是如果在頻繁輸出javascript腳本的網頁中,可能會對網頁的客戶端執行效果產生影響。因為javascript腳本塊在客戶端調用方法之前還是客戶端調用方法之后效果可能會不一樣。
    下面在Home窗體的Page_Load事件中添加代碼,如下:

    ?

    using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; public partial class Home : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { Response.Write("<script language='javascript'>alert('" + DateTime.Now.ToString() + "')</script>"); } } }

    ?

    ?這樣每次運行Home.aspx頁面的時候都會彈出一個對話框,如下圖:

    ?

    ?

    這不是我們所關心的,我們關注的是生成的HTML代碼,如下:

    ?

    <script language='javascript'>alert('2008-9-21 0:22:52')</script> <!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><title> 無標題頁 </title></head> <body> <form name="form1" method="post" action="Home.aspx" id="form1"> <div> <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJNzgzNDMwNTMzZGTB6tgIyCoS2q3pZeKmhFwC24pQzw==" /> </div> <div> </div> </form> </body> </html>

    ?

    ?

    可以看見輸出的javascript代碼在<html></html>標記之外。
    在Page類中有一個ClientScript屬性,它是ClientScriptManager的實例,這個類是在asp.net2.0中新增的。ClientScriptManager有如下幾個常用方法:
    RegisterClientScriptBlock方法:向 Page 對象注冊客戶端腳本。
    RegisterStartupScript方法:向 Page 對象注冊啟動腳本。
    ClientScriptManager類通過鍵string和Type來唯一標識腳本。具有相同類型的鍵和Type的腳本識為同一腳本。
    下面對Home窗體的Page_Load事件中輸入如下代碼:

    ?

    using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; public partial class Home : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { 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>"); } //Response.Write("<script language='javascript'>alert('" + DateTime.Now.ToString() + "')</script>"); } }

    ?

    執行該頁面時,會彈出兩個提示窗口,生成的HTML代碼如下:

    ?

    <!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><title> 無標題頁 </title></head> <body> <form name="form1" method="post" action="Home.aspx" id="form1"> <div> <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJNzgzNDMwNTMzZGTB6tgIyCoS2q3pZeKmhFwC24pQzw==" /> </div> <script language='javascript'>alert('ClientScriptBlock')</script> <div> </div> <script language='javascript'>alert('StartupScript')</script></form> </body> </html>

    ?

    可以看出上面的兩個方法輸出的javascript腳本都在<form></form>標記之內,不會破環文章的結構,而且RegisterClientScriptBlock方法輸出的javascript腳本代碼塊靠近<form>標記的開始標記,而RegisterStartupScript方法輸出的javascript腳本代碼塊靠近<form>標記的結束標記,了解這一點對于控制動態添加的客戶端腳本的時間是非常有利的。

    ?

    ?

    回調技術(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" οnblur="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> </html>

    ?

    ?? 上面的頁面中我已經添加了足夠詳盡的注視,不過我還是要說明幾點:

    ? (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)"?/>
  • (3)

  • csm.GetCallbackEventReference(this,?"args","Success","","Error",false);
  • 中的"Success"和"Error"分別代表客戶端的javascript函數,可以在代碼中見到,其中"Success"代表調用服務器端方法成功后要執行的客戶端方法名,"Error"代表調用服務器端方法失敗時調用的客戶端方法名。

    該頁面在客戶端生成的HTML代碼如下:

    ?

    <!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> </head> <body> <form name="form1" method="post" action="register.aspx" id="form1"> <div> <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" /> <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" /> <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMjA0MjMxNTU1OGRkIv6UMIqGy3vfPLfPRjEbuTwUrf8=" /> </div> <script type="text/javascript"> <!-- var theForm = document.forms['form1']; if (!theForm) { theForm = document.form1; } function __doPostBack(eventTarget, eventArgument) { if (!theForm.onsubmit || (theForm.onsubmit() != false)) { theForm.__EVENTTARGET.value = eventTarget; theForm.__EVENTARGUMENT.value = eventArgument; theForm.submit(); } } // --> </script> <script src="/WebResource.axd?d=CcZ-_AaHZnD65xnNHEUijg2&t=633578466781093750" type="text/javascript"></script> <script type="text/javascript"> <!-- function CallServerMethod(args, context) { WebForm_DoCallback('__Page',args,Success,"",Error,false); }// --> </script> <table border="1" cellpadding="0" cellspacing="0" width="400px"> <tr> <td width="100px">用戶名</td><td><input type="text" size="10" maxlength="20" id="txtUserName" οnblur="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> <script type="text/javascript"> <!-- WebForm_InitCallback();// --> </script> </form> </body> </html>

    ?

    在生成的HTML代碼中多了幾段javascipt教本塊,下面分別說明:

    (1)第一部分

    ?

    <script type="text/javascript"> <!-- var theForm = document.forms['form1']; if (!theForm) { theForm = document.form1; } function __doPostBack(eventTarget, eventArgument) { if (!theForm.onsubmit || (theForm.onsubmit() != false)) { theForm.__EVENTTARGET.value = eventTarget; theForm.__EVENTARGUMENT.value = eventArgument; theForm.submit(); } } // --> </script>

    ?

    這部分代碼是每個asp.net頁面發送到客戶端都會生成的,用于提交當前表單,其中eventTarget參數表示激發提交事件的控件,eventArgument參數表示發生該事件時的參數信息。

    ?

    (2)第二部分

    ?

    <script src="/WebResource.axd?d=CcZ-_AaHZnD65xnNHEUijg2&t=633578466781093750" type="text/javascript"></script>


    這部分代碼是用來生成一些用于Ajax調用的js腳本。說穿了,asp.net之所以開發起來方便,是因為微軟在幕后默默地為我們做了很多工作,回調的本質其實就是Ajax調用。


    我們可以將“/WebResource.axd?d=CcZ-_AaHZnD65xnNHEUijg2&amp;t=633578466781093750”這部分拷貝到瀏覽器地址欄中,如下圖:

    ?

    ?

    回車之后會彈出一個下載文件對話框,如下圖:

    ?

    將這個頁面保存到本地,雖然默認的保存文件的后綴為“.axd”,但它其實是一個文本文件,里面是一些javascript代碼,我們可以用記事本打開,在里面我們可以看到“WebForm_DoCallback”這個方法,如下:

    ?

    ?

    在這個axd文件里做了很多幕后工作,所以我們的回調才相對比較簡單。

    ?

    (3)第三部分

    ?

    <script type="text/javascript"> <!-- function CallServerMethod(args, context) { WebForm_DoCallback('__Page',args,Success,"",Error,false); }// --> </script>

    ?

    這部分代碼是后臺生成的,通過獲取Page類的ClientScript屬性,也就是ClientScriptManager的實例注冊到頁面的,里面定義了兩個javascript函數:CallServerMethod函數和WebForm_DoCallback函數,并且是在CallServerMethod函數中調用WebForm_DoCallback函數。

    ?

    (4)第四部分

    ?

    <script type="text/javascript"> <!-- WebForm_InitCallback();// --> </script>

    ?

    這部分代碼也是幕后生成的,這個javascript函數也可以在那個axd文件中找到。如下圖:

    ?

    當我們在以除“admin”之外的字符串作為用戶名并移開焦點之后,會得到可以注冊的提示,如下圖:

    ?

    當我們輸入“admin”作為用戶名時的結果:

    ?

    另外,我們將服務器端執行的方法做如下處理,也就是RaiseCallbackEvent(String eventArgument)這個方法,我們在這里拋出一個異常,代碼如下:

    ?

    // 定義在服務器端運行的回調方法. public void RaiseCallbackEvent(String eventArgument) { /* if(eventArgument.ToLower().IndexOf("admin")!=-1) { result=eventArgument+"不能作為用戶名注冊。"; } else { result=eventArgument+"可以注冊。"; } */ throw new Exception(); }

    ?

    再次運行,無論我們以什么作為用戶名,都會得到如下結果:

    ?

    ?

    之所以會出現“發生了異常”這個字符串,是因為我們定義了function Error(args, context)這個javascript函數,并且把它作為調用服務器端方法發生異常時的客戶端處理函數,它的處理方式就是顯示“發生了異常”這個字符串。

    ?

    • 查看圖片附件

    總結

    以上是生活随笔為你收集整理的asp.net夜话之五:Page类和回调技术的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。