在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页面,代码如下:

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">

6 <script language="javascript">
7 //客户端执行的方法

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>

上面的页面中我已经添加了足够详尽的注视,不过我还是要说明几点:
(1)

  1. <%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>

这句表示当前页面实现了ICallbackEventHandler接口,如果采用页面与代码分离的模式,后台cs代码则应是:

  1. public partial class Register : System.Web.UI.Page, ICallbackEventHandler
  2. {
  3. //cs代码
  4. }

(2)

  1. <input type="text" size="10" maxlength="20" id="txtUserName" onblur="CallServerMethod(txtUserName.value,null)" />

这里有一个onblur="CallServerMethod(txtUserName.value,null),表示当用户名文本框失去焦点之后激发CallServerMethod这个客户端方法,这个客户端方法是由asp.net动态生成的。
(3)

  1. csm.GetCallbackEventReference(this, "args","Success","","Error",false);

中的"Success"和"Error"分别代表客户端的javascript函数,可以在代码中见到,其中"Success"代表调用服务器端方法成功后要执行的客户端方法名,"Error"代表调用服务器端方法失败时调用的客户端方法名。

该页面在客户端生成的HTML代码如下:


2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

4 <script language="javascript">
5 //客户端执行的方法

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&amp;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>
78

在生成的HTML代码中多了几段javascipt教本块,下面分别说明:
(1)第一部分

  1. <script type="text/javascript">
  2. <!--
  3. var theForm = document.forms['form1'];
  4. if (!theForm) {
  5. theForm = document.form1;
  6. }
  7. function __doPostBack(eventTarget, eventArgument) {
  8. if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
  9. theForm.__EVENTTARGET.value = eventTarget;
  10. theForm.__EVENTARGUMENT.value = eventArgument;
  11. theForm.submit();
  12. }
  13. }
  14. // -->
  15. </script>

这部分代码是每个asp.net页面发送到客户端都会生成的,用于提交当前表单,其中eventTarget参数表示激发提交事件的控件,eventArgument参数表示发生该事件时的参数信息。

(2)第二部分

  1. <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)第三部分

  1. <script type="text/javascript">
  2. <!--
  3. function CallServerMethod(args, context) {
  4. WebForm_DoCallback('__Page',args,Success,"",Error,false);
  5. }// -->
  6. </script>

这部分代码是后台生成的,通过获取Page类的ClientScript属性,也就是ClientScriptManager的实例注册到页面的, 里面定义了两个javascript函数:CallServerMethod函数和WebForm_DoCallback函数,并且是在 CallServerMethod函数中调用WebForm_DoCallback函数。

(4)第四部分

  1. <script type="text/javascript">
  2. <!--
  3. WebForm_InitCallback();// -->
  4. </script>

这部分代码也是幕后生成的,这个javascript函数也可以在那个axd文件中找到。如下图:

后,会得到可以注册的提示,如下图:

当我们输入“admin”作为用户名时的结果:

另外,我们将服务器端执行的方法做如下处理,也就是RaiseCallbackEvent(String eventArgument)这个方法,我们在这里抛出一个异常,代码如下:

  1. // 定义在服务器端运行的回调方法.
  2. public void RaiseCallbackEvent(String eventArgument)
  3. {
  4. /*
  5. if(eventArgument.ToLower().IndexOf("admin")!=-1)
  6. {
  7. result=eventArgument+"不能作为用户名注册。";
  8. }
  9. else
  10. {
  11. result=eventArgument+"可以注册。";
  12. }
  13. */
  14. throw new Exception();
  15. }

再次运行,无论我们以什么作为用户名,都会得到如下结果:

之所以会出现“发生了异常”这个字符串,是因为我们定义了function Error(args, context)这个javascript函数,并且把它作为调用服务器端方法发生异常时的客户端处理函数,它的处理方式就是显示“发生了异常”这个字符串。

ASP.NET 回调技术(CallBack)的更多相关文章

  1. Asp.net回调技术Callback学习

    .aspx: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.a ...

  2. 【ASP.NET 基础】Page类和回调技术

    Page 类有一个 IsPostBack 属性,这个属性用来指示当前页面是第一次加载还是响应了页面上某个控件的服务器事件导致回发而加载. 1.asp.net页面的声明周期 asp.net页面运行的时候 ...

  3. Asp.Net--回调技术

    实现回调技术需要以下步骤: 1.实现ICallbakEventHandler 2.实现接口中的方法:RaiseCallbackEvent 3.实现GetCallbackResult 方法 解释 参数 ...

  4. 理解javascript中的回调函数(callback)【转】

    在JavaScrip中,function是内置的类对象,也就是说它是一种类型的对象,可以和其它String.Array.Number.Object类的对象一样用于内置对象的管理.因为function实 ...

  5. C++回调函数(callback)的使用

    什么是回调函数(callback)    模块A有一个函数foo,他向模块B传递foo的地址,然后在B里面发生某种事件(event)时,通过从A里面传递过来的foo的地址调用foo,通知A发生了什么事 ...

  6. [转]C++回调函数(callback)的使用

    原文地址:http://blog.sina.com.cn/s/blog_6568e7880100p77y.html 什么是回调函数(callback)    模块A有一个函数foo,他向模块B传递fo ...

  7. JAVA回调机制(CallBack)详解

    序言 最近学习java,接触到了回调机制(CallBack).初识时感觉比较混乱,而且在网上搜索到的相关的讲解,要么一言带过,要么说的比较单纯的像是给CallBack做了一个定义.当然了,我在理解了回 ...

  8. Android中的接口回调技术

    Android中的接口回调技术有很多应用的场景,最常见的:Activity(人机交互的端口)的UI界面中定义了Button,点击该Button时,执行某个逻辑. 下面参见上述执行的模型,讲述James ...

  9. js回调函数(callback)理解

    Mark! js学习 不喜欢js,但是喜欢jquery,不解释. 自学jquery的时候,看到一英文词(Callback),顿时背部隐隐冒冷汗.迅速google之,发现原来中文翻译成回调.也就是回调函 ...

随机推荐

  1. CLR内存管理

    CLR管理内存的区域,主要有三块,分别为: 1.线程的堆栈:(在程序应该编译过程为值类型实例分配好内存) 用于分配值类型实例.堆栈主要由操作系统管理,而不受垃圾收集器的控制,当值类型实例所在方法结束时 ...

  2. Linux Kernel 3.11 正式版发布

    Linus 发布 了 3.11 版本的 Linux 内核.该版本值得关注的新特性有: Lustre 分布式文件系统.透明的 ARM 架构的大数据页支持:ARM64 上的 Xen 和 KVM 虚拟化:O ...

  3. PhoneJS - HTML5 JavaScript 移动开发框架

    大伙儿都知道有很多基于HTML5的移动应用框架.下一代开发工具将帮助开发者远离那些难学和让人费劲的原生SDK语言,如Objective-C,Java等.大家都知道,HTML5代表着交叉平台如移动应用程 ...

  4. 意外作出了一个javascript的服务器,可以通过js调用并执行任何java(包括 所有java 内核基本库)及C#类库,并最终由 C# 执行你提交的javascript代码! 不敢藏私,特与大家分

    最近研发BDC 云开发部署平台的数据路由及服务管理器意外作出了一个javascript的服务器,可以通过js调用并执行任何java(包括 所有java 内核基本库)及C#类库,并最终由 C# 执行你提 ...

  5. Dynamic CRM 2013学习笔记(十二)实现子表合计(汇总,求和)功能的通用插件

    上一篇 Dynamic CRM 2013学习笔记(十一)利用Javascript实现子表合计(汇总,求和)功能 , 介绍了如何用js来实现子表合计功能,这种方法要求在各个表单上添加js方法,如果有很多 ...

  6. 到底是 const 还是 static readonly

    真的一样? const 和 static readonly 常在程序中用来声明常量,调用方法也没有什么不同,他们真的一样吗?我们可以做个试验. 程序集内的常量 现在我们建立一个程序,里面有一个MyCl ...

  7. Gradle里配置jetty实现静态资源的热部署

    通过Gradle我们可以很方便的使用内置jetty启动我们的web程序,在本地进行调试.但是在使用的过程中,我发现了几个问题,导致本地调试的效率大受影响. 如果使用gradle jettyRun启动j ...

  8. LInux iptables学习

    作者原文 : http://blog.chinaunix.net/uid-9950859-id-98277.html       要在网上传输的数据会被分成许多小的数据包,我们一旦接通了网络,会有很多 ...

  9. atitit. 解决org.hibernate.SessionException Session is closed

    atitit. 解决org.hibernate.SessionException Session is closed   #--现象:: org.hibernate.SessionException ...

  10. DL 小记之序

    在开通博客的1小时03分钟50秒,我写下了第一篇文字.不知道从什么时候开始,什么东西都有个期限,在写下几小时几分几秒之后,我总是习惯性的加上不知道从什么时候开始. 本博客不含惊天动地的故事,想看故事请 ...