在写程序的过程中,一些小的Ajax效果我不大喜欢去用Ajax框架来做,为了一点点效果就去动用Ajax框架这个相对庞大的家伙显然有点不明智。很多简单的Ajax效果,利用 ICallbackEventHandler接口 ,加点简单的代码就可以很轻松的完成。下面将演示怎样利用ICallbackEventHandler接口 实现客户端回调,实现 检查用户名是可用 的实例。
效果


实现 既然是利用 ICallbackEventHandler接口来实现,那我们先来了解一下ICallbackEventHandler接口。 ICallbackEventHandler 接口用于指示控件可以作为服务器的回调事件的目标。任何需要接收回调事件的控件都要实现 ICallbackEventHandler 接口。继承这个接口需要实现两个方法 RaiseCallbackEvent和 GetCallbackResult,其中, RaiseCallbackEvent用来处理客户端提交的请求, RaiseCallbackEvente有一个string类型的参数,是客户端提交到服务器端的参数。而 GetCallbackResult方法则负责把服务器端的处理结果返回到客户端。
既然要实现回调功能,客户端当然也少不了要有一个向服务器端发送回调请求的函数。用ClientScriptManager类的GetCallbackEventReference方法可以在页面注册一个回调函数。下面来看看GetCallbackEventReference方法在 MSDN中的解释:
语法:
public string GetCallbackEventReference(
Control control,
string argument
string clientCallback
string context
string clientErrorCallback
bool useAsync
)
参数
control
处理客户端回调的服务器 Control。该控件必须实现 ICallbackEventHandler 接口并提供 RaiseCallbackEvent 方法。
argument 从客户端脚本传递给服务器端的一个参数
clientCallback
一个客户端事件处理程序的名称,该处理程序接收成功的服务器端事件的结果
context
启动回调之前在客户端计算的客户端脚本。脚本的结果传回客户端事件处理程序
clientErrorCallback
客户端事件处理程序的名称,该处理程序在服务器端事件处理程序出现错误时接收结果
useAsync
true 表示同步执行回调 false 表示异步执行回调
返回值
调用客户端回调的客户端函数的名称。
了解了上面两点以后,我们就开始来实现这个功能。先要修改页面,继承 ICallbackEventHandler接口,以让页面支持回调
public partial class _Default : System.Web.UI.Page ,ICallbackEventHandler
然后我们模拟一个已存在用户的列表,在这里为了简单起见(其实是懒,呵呵),我用了一个string的数组,当然,也可以连接到数据库取得已存在的用户
string[] UserNames = { "LixingTie", "生铁" };
有了已存在用户以后,让我们来实现 ICallbackEventHandler接口的成员。首先是实现 RaiseCallbackEvent方法处理客户端提交的结果。为了保存 RaiseCallbackEvent方法处理的结果,我声明了一个变量 CallbackResult来保存。
string CallbackResult = null;
public void RaiseCallbackEvent(string eventArgument)
{
if(eventArgument == "生铁猪")
throw new Exception("请别进行人身攻击!");
CallbackResult = Array.IndexOf(UserNames, eventArgument) != -1 ? "该帐户已注册" : "未注册用户";
}
这里,在 RaiseCallbackEvent方法中,对客户端提交过来的用户名参数eventArgument进行了判断,如果用户名是 "生铁猪" 的话,就抛出一个导常,这主要是用来测试客户端事件处理服务器端处理出错的情况,这里先不理。如果客户端提交上来的用户不是 "生铁猪" ,则判断用户名是否已存在(用户是否在 UserNames 中, 是否为 "LixingTie", "生铁" 之一),如果存在的话,处理结果为 "该帐户已注册" 否则为 "未注册用户"。
继续实现 ICallbackEventHandler接口 的另一个成员 GetCallbackResult 以把处理结果返回到客户端。
public string GetCallbackResult()
{
return CallbackResult;
}
这个方法的实现就比较简单,就单纯的返回 RaiseCallbackEvent方法的处理结果 CallbackResult;
实现了 ICallbackEventHandler接口 之后,这时我们需要在客户端注册一个向服务器端发送回调请求的函数,我们在页面的Load事件中实现这一步骤
protected void Page_Load(object sender, EventArgs e)
{
if (Page.Request.Browser.SupportsXmlHttp)
{
ClientScriptManager cs = Page.ClientScript;
string callbackScript = cs.GetCallbackEventReference(this, "GetClientUserName()", "OnCallbackCompleted", null, "OnServerError", true);
string callbackScriptMethod = "function CallbackScriptMethod() { " + callbackScript + " ;}";
cs.RegisterClientScriptBlock(this.GetType(), "CallbackScriptMethod", callbackScriptMethod, true);
}
}
先用 ClientScriptManager cs = Page.ClientScript;来获得页页的 ClientScriptManager引用。然后通过 GetCallbackEventReference注册发送回调请求的函数, cs.GetCallbackEventReference(this, "GetClientUserName()", "OnCallbackCompleted", "", "OnServerError", true);
参数一 this 代表处理客户端回调的控件为当前页。
参数二 "GetClientUserName()" 是页面上的一个javascript函数,该函数返回的是用户在TextBox中输入的用户名,用户名将提交到服务器进行判断,GetClientUserName()函数的具体内容将在下面补上。
参数三 "OnCallbackCompleted" 表示接收服务器端事件处理结果的javascript函数为 OnCallbackCompleted 函数。
参数四 null,这个实例不需要用到这个参数,所以给它一个空值。这个参数的具体作用见上面MSDN的解释。
参数五 "OnServerError",这个参数指定了当服务器端处理出错时,由客户端的javascript函数OnServerError()来接收错误信息并处理。在这个实例中,当用户在TextBox里输入 "生铁猪" 的时候服务器端会抛出错误并调用客户端函数OnServerError()处理错误并显示。
参数六 true 表示同步执行这次回调。
GetCallbackEventReference函数将根据参数返回一个string类型的发送回调请求的脚本,我们把这个脚本保存在callbackScript变量中。
string callbackScriptMethod = "function CallbackScriptMethod() { " + callbackScript + " ;}"; 这条语句将拼接一个名为CallbackScriptMethod的javascript脚本,然后把回调请求脚本放在这个函数体内。这样做以后就可以在javascript里通过CallbackScriptMethod() 函数引发回调。
cs.RegisterClientScriptBlock(this.GetType(), "CallbackScriptMethod", callbackScriptMethod, true); 这条语句把引发回调的函数 CallbackScriptMethod()发送到客户端。
至于 if (Page.Request.Browser.SupportsXmlHttp)这句是用来检测客户端浏览器是否XmlHttp,因为回调功能使用了XmlHttp,所以,在不支持XmlHttp的浏览器中,这个功能是不能用的。
至此,服务器端的逻辑就已经完成了。后台完整代码如下



























































现在开始,我们来实现页面的界面和客户端的javascript。页面的内容很简单,就一个用来输入用户名的TextBox,一个发起回调的HTML Button,和一个显示信息的SPAN
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="ClientUserName" runat="server"></asp:TextBox>
<input id="CheckBtn" type="button" value="检查帐户" onclick="CheckUserName();" />
<span id="message" style="color:Red;"></span>
</div>
</form>
</body>
现在我们来补全刚刚服务器代码中要用到的javascript。代码如下:
<script language="javascript" type="text/javascript">
function GetClientUserName()
{
return document.getElementById("<%=ClientUserName.ClientID %>").value;
}
function CheckUserName()
{
CallbackScriptMethod();
}
function OnCallbackCompleted(CallbackResult,context)
{
document.getElementById("message").innerText = CallbackResult;
}
function OnServerError(error)
{
alert("错误信息 " + error);
}
</script>
GetClientUserName为刚刚服务器端代码需要用到的获取用户输入的用户名的函数。通过document.getElementById("<%=ClientUserName.ClientID %>").value;取得Textbox ClientUserName的值。注意这里用的ID是ClientUserName.ClientID而不是直接用ClientUserName,原因是服务器控件的ID和服务器发送到客户端的ID可能会不同。ClientID是获取发送到客户端的ID。
OnCallbackCompleted 是接收服务器端处理结果的函数。
OnServerError 是处理服务器出错的函数。
CheckUserName 是点击检查按钮时候调用的函数,这个函数将调用服务器端生成的引发回调的函数CallbackScriptMethod(),引发回调。
完整的页面代码如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!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>CallbackTest</title>
<script language="javascript" type="text/javascript">
function GetClientUserName()
{
return document.getElementById("<%=ClientUserName.ClientID %>").value;
}
function CheckUserName()
{
CallbackScriptMethod();
}
function OnCallbackCompleted(CallbackResult,context)
{
document.getElementById("message").innerText = CallbackResult;
}
function OnServerError(error)
{
alert("错误信息 " + error);
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="ClientUserName" runat="server"></asp:TextBox>
<input id="CheckBtn" type="button" value="检查帐户" onclick="CheckUserName();" />
<span id="message" style="color:Red;"></span>
</div>
</form>
</body>
</html>
到这里这个例子就完成了。我们可以在IE中看一下效果。(注:调试客户端错误处理的时候请不要在Debug模式下调试页面,因为在Debug模式下抛出异常的话VS会自动切换到代码中检查代码。右击页面选"在浏览器中查看"就行了。)



可以看到,输入"生铁猪"的时候,除了我们原先定义的错误信息外,后面还符加有一段字符,这段字符具体代表的是什么我不大清楚,我想应该是错误的一些附加信息吧。不知道这样认为对不对,知道的朋友请告诉我一下,谢谢。
总结 感觉上,.Net带给我们的便利还是很多的,我们只需要编写少量代码就可以实现这个回调功能。但是我们在享受.Net带给我们的便利的同时,也千万别忘了这种便利是建立在损耗性能的前题下的。个人认为,在web编程的过程中,如果不是在后台需要访问的元素都尽量用HTML控件去完成,少点用服务器控件。因为服务器控件都是经过封装的,每个控件都有它自己的生命周期,需要经过初始化,加载状态,Render等等步骤最后才输出为我们在客端看到的元素,这必定是要损耗服务器性能的。
程序之路还在摸索学习之中,如果我有什么错误的地方,请各位大家多多指正,谢谢。
相关 源项目下载: 点击这里下载