在asp.net中客戶端與服務器端的交互默認都是整頁面提交, 此時客戶端將當前頁面表單中的數據(包括一些自動生成的隱藏域)都提交到服務器端,服務器從新實例化一個當前頁面類的實例響應這個請求,而後將整個頁面的 內容從新發送到客戶端,這種處理方式對運行結果沒什麼影響,不過這種方式加劇了網絡的數據傳輸負擔、加大了服務器的工做壓力,而且用戶還須要等待最終處理 結果。假如是咱們但願有這麼一個功能,當用戶填寫完用戶名以後就檢查服務器數據庫裏是否已存在該用戶名,若是存在就給出已經存在此用戶名的提示,若是不存 在就提示用戶此用戶名可用,對於這種狀況其實只須要傳遞一個用戶名做爲參數便可,上面的作法卻須要提交整個表單,有點小題大作。解決上面的問題的辦法目前 主流作法有三種:純javascript實現、微軟Ajax類庫實現還有用AjaxPro實現。後兩種作法在稍後的文章中會講到,這裏我講另一種實現: 經過回調技術。javascript
建立實現回調技術的網頁與普通asp.net網頁相似,只不過還須要作如下特殊工做:
(1)讓當前頁面實現 ICallbackEventHandler接口,這個接口定義了兩個方法:string GetCallbackResult ()方法和void RaiseCallbackEvent (string eventArgument)方法。其中GetCallbackResult ()方法的做用是返回以控件爲目標的回調事件的結果,RaiseCallbackEvent()方法的做用是處理以控件爲目標的回調事件。
(2) 爲當前頁提供三個javascript客戶端腳本函數。一個javascript函數用於執行對服務器的實際請求,在這個函數中能夠提供一個字符串類型的 參數發送到服務器端;另外一個javascript函數用於接收服務器端方法的執行後返回的字符串類型結果,並處理這個結果;還有一個是執行對服務器請求的 幫助函數,在服務器代碼中經過GetCallbackEventReference()方法獲取這個方法的引用時由asp.net自動生成這個函數。
下面我以一個詳細的例子來說述如何使用回調,用Dreamweaver建立一個Register. aspx頁面,代碼以下:html
1 <%@ Page Language="C#" %>
2 <%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>
3 <%@ Import Namespace="System.Text" %>
4 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5
6 <script language="javascript">
7 //客戶端執行的方法
8
9 //下面的方法是接收並處理服務器方法執行的返回結果
10 function Success(args, context)
11 {
12 message.innerText = args;
13 }
14 //下面的方式是當接收服務器方法處理的結果發生異常時調用的方法
15 function Error(args, context)
16 {
17 message.innerText = '發生了異常';
18 }
19 </script>
20
21 <script language="c#" runat="server">
22 string result="";
23 // 定義在服務器端運行的回調方法.
24 public void RaiseCallbackEvent(String eventArgument)
25 {
26
27 if (eventArgument.ToLower().IndexOf("admin") != -1)
28 {
29 result = eventArgument + "不能做爲用戶名註冊。";
30 }
31 else
32 {
33 result = eventArgument + "能夠註冊。";
34 }
35
36 //throw new Exception();
37 }
38
39 //定義返回回調方法執行結果的方法
40 public string GetCallbackResult()
41 {
42 return result;
43 }
44
45 //服務器上執行的方法
46 public void Page_Load(Object sender, EventArgs e)
47 {
48 // 獲取當前頁的ClientScriptManager的引用
49 ClientScriptManager csm = Page.ClientScript;
50
51 // 獲取回調引用。會在客戶端生成WebForm_DoCallback方法,調用它來達到異步調用。這個方式是微軟寫的方法,會被髮送到客戶端
52 //注意這裏的"Success"和"Error"兩個字符串分別客戶端代碼中定義的兩個javascript函數
53 //下面的方法最後一個參數的意義:true表示執行異步回調,false表示執行同步回調
54 String reference = csm.GetCallbackEventReference(this, "args", "Success", "", "Error",false);
55 String callbackScript = "function CallServerMethod(args, context) {\n" +reference + ";\n }";
56
57 // 向當前頁面註冊javascript腳本代碼
58 csm.RegisterClientScriptBlock(this.GetType(), "CallServerMethod",
59 callbackScript, true);
60 }
61 </script>
62
63 <html >
64 <head runat="server">
65 <title>無題のページ</title>
66 </head>
67 <body>
68 <form id="form1" runat="server">
69 <table border="1" cellpadding="0" cellspacing="0" width="400px">
70 <tr>
71 <td width="100px">用戶名</td><td><input type="text" size="10" maxlength="20"id="txtUserName" onblur="CallServerMethod(txtUserName.value,null)" /><span id="message"></span></td>
72 </tr>
73 <tr>
74 <td>密碼</td><td><input type="password" size="10" maxlength="20" id="txtPwd" /></td>
75 </tr>
76 </table>
77 </form>
78 </body>
79 </html>java
上面的頁面中我已經添加了足夠詳盡的注視,不過我仍是要說明幾點:
(1)web
這句表示當前頁面實現了ICallbackEventHandler接口,若是採用頁面與代碼分離的模式,後臺cs代碼則應是:數據庫
(2)c#
這裏有一個onblur="CallServerMethod(txtUserName.value,null),表示當用戶名文本框失去焦點以後激發CallServerMethod這個客戶端方法,這個客戶端方法是由asp.net動態生成的。
(3)瀏覽器
中的"Success"和"Error"分別表明客戶端的javascript函數,能夠在代碼中見到,其中"Success"表明調用服務器端方法成功後要執行的客戶端方法名,"Error"表明調用服務器端方法失敗時調用的客戶端方法名。服務器
該頁面在客戶端生成的HTML代碼以下:網絡
1
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
4 <script language="javascript">
5 //客戶端執行的方法
6
7 //下面的方法是接收並處理服務器方法執行的返回結果
8 function Success(args, context)
9 {
10 message.innerText = args;
11 }
12 //下面的方式是當接收服務器方法處理的結果發生異常時調用的方法
13 function Error(args, context)
14 {
15 message.innerText = '發生了異常';
16 }
17 </script>
18
19
20
21 <html xmlns="http://www.w3.org/1999/xhtml" >
22 <head><title>
23 無題のページ
24 </title></head>
25 <body>
26 <form name="form1" method="post" action="Register.aspx" id="form1">
27 <div>
28 <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
29 <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value=""/>
30 <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE"value="/wEPDwUKMTUxMzcyMjQyN2RktUwTa0pYHOlQ0OTLFd6fte0EGow=" />
31 </div>
32
33 <script type="text/javascript">
34 <!--
35 var theForm = document.forms['form1'];
36 if (!theForm) {
37 theForm = document.form1;
38 }
39 function __doPostBack(eventTarget, eventArgument) {
40 if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
41 theForm.__EVENTTARGET.value = eventTarget;
42 theForm.__EVENTARGUMENT.value = eventArgument;
43 theForm.submit();
44 }
45 }
46 // -->
47 </script>
48
49
50 <script src="/web/WebResource.axd?d=jAi7Db33LHl_8HdPSGuzAg2&t=633608119083845334" type="text/javascript"></script>
51
52
53 <script type="text/javascript">
54 <!--
55 function CallServerMethod(args, context) {
56 WebForm_DoCallback('__Page',args,Success,"",Error,false);
57 }// -->
58 </script>
59
60 <table border="1" cellpadding="0" cellspacing="0" width="400px">
61 <tr>
62 <td width="100px">用戶名</td><td><input type="text" size="10" maxlength="20"id="txtUserName" onblur="CallServerMethod(txtUserName.value,null)" /><span id="message"></span></td>
63 </tr>
64 <tr>
65 <td>密碼</td><td><input type="password" size="10" maxlength="20" id="txtPwd" /></td>
66 </tr>
67 </table>
68
69
70 <script type="text/javascript">
71 <!--
72
73 WebForm_InitCallback();// -->
74 </script>
75 </form>
76 </body>
77 </html>
78asp.net
在生成的HTML代碼中多了幾段javascipt教本塊,下面分別說明:
(1)第一部分
這部分代碼是每一個asp.net頁面發送到客戶端都會生成的,用於提交當前表單,其中eventTarget參數表示激發提交事件的控件,eventArgument參數表示發生該事件時的參數信息。
(2)第二部分
這部分代碼是用來生成一些用於Ajax調用的js腳本。說穿了,asp.net之因此開發起來方便,是由於微軟在幕後默默地爲咱們作了不少工做,回調的本質其實就是Ajax調用。
咱們能夠將「/WebResource.axd?d=CcZ-_AaHZnD65xnNHEUijg2&t=633578466781093750」這部分拷貝到瀏覽器地址欄中,以下圖:
回車以後會彈出一個下載文件對話框,以下圖:
將這個頁面保存到本地,雖然默認的保存文件的後綴爲「.axd」,但它實際上是一個文本文件,裏面是一些javascript代碼,咱們能夠用記事本打開,在裏面咱們能夠看到「WebForm_DoCallback」這個方法,以下:
在這個axd文件裏作了不少幕後工做,因此咱們的回調才相對比較簡單。
(3)第三部分
這部分代碼是後臺生成的,經過獲取Page類的ClientScript屬性,也就是ClientScriptManager的實例註冊到頁面的, 裏面定義了兩個javascript函數:CallServerMethod函數和WebForm_DoCallback函數,而且是在 CallServerMethod函數中調用WebForm_DoCallback函數。
(4)第四部分
這部分代碼也是幕後生成的,這個javascript函數也能夠在那個axd文件中找到。以下圖:
後,會獲得能夠註冊的提示,以下圖:
當咱們輸入「admin」做爲用戶名時的結果:
另外,咱們將服務器端執行的方法作以下處理,也就是RaiseCallbackEvent(String eventArgument)這個方法,咱們在這裏拋出一個異常,代碼以下:
再次運行,不管咱們以什麼做爲用戶名,都會獲得以下結果:
之因此會出現「發生了異常」這個字符串,是由於咱們定義了function Error(args, context)這個javascript函數,而且把它做爲調用服務器端方法發生異常時的客戶端處理函數,它的處理方式就是顯示「發生了異常」這個字符串。