前言
在 asp.net 中客户端与服务器端的交互默认都是整页面提交,此时客户端将当前页面表单中的数据(包括一些自动生成的隐藏域)都提交到服务器端,服务器重新实例化一个当前页面类的实例响应这个请求,然后将整个页面的内容重新发送到客户端,这种处理方式对运行结果没什么影响,不过这种方式加重了网络的数据传输负担、加大了服务器的工作压力,并且用户还需要等待最终处理结果。
假如是我们希望有这么一个功能,当用户填写完用户名之后就检查服务器数据库里是否已存在该用户名,如果存在就给出已经存在此用户名的提示,如果不存在就提示用户此用户名可用,对于这种情况其实只需要传递一个用户名作为参数即可,上面的做法却需要提交整个表单,有点小题大做。
解决上面的问题的办法目前主流做法有三种:纯 javascript 实现、微软 Ajax 类库实现还有用 AjaxPro 实现。这里通过另外一种实现:通过回调技术。
特殊工作
创建实现回调技术的网页与普通 asp.net 网页类似,只不过还需要做以下特殊工作:
(1)让当前页面实现 ICallbackEventHandler 接口,这个接口定义了两个方法:stringGetCallbackResult ()方法和 void RaiseCallbackEvent (string eventArgument)方法。其中 GetCallbackResult ()方法的作用是返回以控件为目标的回调事件的结果,RaiseCallbackEvent()方法的作用是处理以控件为目标的回调事件。
(2)为当前页提供三个 javascript 客户端脚本函数。一个 javascript 函数用于执行对服务器的实际请求,在这个函数中可以提供一个字符串类型的参数发送到服务器端;另一个javascript 函数用于接收服务器端方法的执行后返回的字符串类型结果,并处理这个结果;还有一个是执行对服务器请求的帮助函数,在服务器代码中通过GetCallbackEventReference()方法获取这个方法的引用时由 asp.net 自动生成这个函数。
前台:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Register.aspx.cs" Inherits="Demo01.Register" %>
<%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>用户注册</title>
<script lang="javascript">
//客户端执行的方法
//接受并处理服务器方法执行的返回结果
function Success(args, context) {
message.innerText = args;
}
//当接收服务器方法处理的结果发生异常时调用的方法
function Error(args, context) {
message.innerText = "发生了异常";
}
</script>
<script lang="C#" runat="server">
string result = "";
//定义在服务器端运行的回掉方法
public void RaiseCallbackEvent(String eventArgument)
{
if (eventArgument.ToLower().IndexOf("admin") != -1)
{
result = eventArgument + "不能作为用户名注册";
}
else
{
result = eventArgument + "可以注册";
}
}
//定义回掉方法执行结果的方法
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>
<!--onblur属性是指当文本框失去焦点的时候激发CallServerMethod这个客户端方法(此方法由asp.net动态生成的)-->
</tr>
<tr>
<td>密码</td>
<td>
<input type="password" size="10" maxlength="20" id="txtPwd" /></td>
</tr>
</table>
</form>
</body>
</html>
后台:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Demo01
{
public partial class Register : System.Web.UI.Page,ICallbackEventHandler
{
public string GetCallbackResult()
{
throw new NotImplementedException();
}
public void RaiseCallbackEvent(string eventArgument)
{
throw new NotImplementedException();
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
}
运行结果
生成的网页源代码
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>
用户注册
</title>
<script lang="javascript">
//客户端执行的方法
//接受并处理服务器方法执行的返回结果
function Success(args, context) {
message.innerText = args;
}
//当接收服务器方法处理的结果发生异常时调用的方法
function Error(args, context) {
message.innerText = "发生了异常";
}
</script>
</head>
<body>
<form method="post" action="./Register.aspx" id="form1">
<div class="aspNetHidden">
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="ea9ctnvhzxsufRcX4ONLZNlBISPq99htd0fEa/aTxbVWG1znaV9ckE+EPp0anjyMPQ8w/1TrZUDvucDvyquUEcp8JRcFNsgcESqMOameBLA=" />
</div>
<script type="text/javascript">
//<![CDATA[
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=pynGkmcFUV13He1Qd6_TZMV6EscnxgvOFPI38fJhmwZSmx9nd-zebkipSWds21YZ7uQyphQG-Gi0yXhyb_0jLw2&t=636476410140000000" type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
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" onblur="CallServerMethod(txtUserName.value,null)" /><span id="message"></span></td>
<!--onblur属性是指当文本框失去焦点的时候激发CallServerMethod这个客户端方法(此方法由asp.net动态生成的)-->
</tr>
<tr>
<td>密码</td>
<td>
<input type="password" size="10" maxlength="20" id="txtPwd" /></td>
</tr>
</table>
<div class="aspNetHidden">
<input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="799CC77D" />
</div>
<script type="text/javascript">
//<![CDATA[
WebForm_InitCallback();//]]>
</script>
</form>
<!-- Visual Studio Browser Link -->
<script type="application/json" id="__browserLink_initializationData">
{"appName":"Firefox","requestId":"45d466125d9b4fcd957516ec10718f8a"}
</script>
<script type="text/javascript" src="http://localhost:8072/b08f8f95aced430b9f95750177eb1817/browserLink" async="async"></script>
<!-- End Browser Link -->
</body>
</html>
注意几点:
- 需要引入命名空间<%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>,后台Register类需要实现ICallbackEventHandler 接口
- οnblur="CallServerMethod(txtUserName.value,null),表示当用户名文本框失去焦点之后激发 CallServerMethod 这个客户端方法,这个客户端方法是由 asp.net动态生成的。
- csm.GetCallbackEventReference(…)方法表示获取一个对客户端函数的引用
文章来自asp夜话,另外其他内容此处不再列出,详情请点击此处