zoukankan      html  css  js  c++  java
  • 利用 ICallbackEventHandler接口 实现客户端回调

    摘要  现在基于.Net的Ajax框架很多,Ajax已经变得很傻瓜化,甚至MS还很狂的说,现在所有的Asp.Net程序员都可以在简历上写会Ajax技术,MS狂妄的资本就是MS的Asp.Net 2.0 Ajax框架。众多的Ajax框架确实给我们开发带来了很多的方便,甚至把Ajax的应用简化到控件拖拉的地步,但这也直接导致了很多人滥用Ajax,只要高兴就套个UpdatePannel,这已经成为很多程序员的习惯,却不知道这样做得到的往往是反效果,增加了服务器的负担。
      在写程序的过程中,一些小的Ajax效果我不大喜欢去用Ajax框架来做,为了一点点效果就去动用Ajax框架这个相对庞大的家伙显然有点不明智。很多简单的Ajax效果,利用 ICallbackEventHandler接口 ,加点简单的代码就可以很轻松的完成。下面将演示怎样利用ICallbackEventHandler接口 实现客户端回调,实现 检查用户名是可用 的实例。

    效果

    实现
      既然是利用ICallbackEventHandler接口来实现,那我们先来了解一下ICallbackEventHandler接口。ICallbackEventHandler 接口用于指示控件可以作为服务器的回调事件的目标。任何需要接收回调事件的控件都要实现 ICallbackEventHandler 接口。继承这个接口需要实现两个方法RaiseCallbackEventGetCallbackResult,其中,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的浏览器中,这个功能是不能用的。

    至此,服务器端的逻辑就已经完成了。后台完整代码如下


    using System;
    using System.Data;
    using System.Configuration;
    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 _Default : System.Web.UI.Page ,ICallbackEventHandler
    {
        
    string CallbackResult = null;
        
    string[] UserNames = "LixingTie""生铁" };

        
    protected void Page_Load(object sender, EventArgs e)
        
    {
            ClientScriptManager cs 
    = Page.ClientScript;
            
    if (Page.Request.Browser.SupportsXmlHttp)
            
    {
                
    string callbackScript = cs.GetCallbackEventReference(this"GetClientUserName()""OnCallbackCompleted"null"OnServerError"true);
                
    string callbackScriptMethod = "function CallbackScriptMethod() { " + callbackScript + " ;}";
                cs.RegisterClientScriptBlock(
    this.GetType(), "CallbackScriptMethod", callbackScriptMethod, true);
            }

            
    else
            
    {
                cs.RegisterStartupScript(
    this.GetType(), "SupportsXmlHttp""alert('你的浏览器不支持XmlHttp,不能使用回调功能!')",true);
            }

        }


        
    public string GetCallbackResult()
        
    {
            
    return CallbackResult;
        }


        
    public void RaiseCallbackEvent(string eventArgument)
        
    {
            
    if(eventArgument == "生铁猪")
                
    throw new Exception("请别进行人身攻击!");
            CallbackResult 
    = Array.IndexOf(UserNames, eventArgument) != -1 ? "该帐户已注册" : "未注册用户";
        }

    }


    现在开始,我们来实现页面的界面和客户端的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等等步骤最后才输出为我们在客端看到的元素,这必定是要损耗服务器性能的。
      程序之路还在摸索学习之中,如果我有什么错误的地方,请各位大家多多指正,谢谢。

    相关  源项目下载:点击这里下载
  • 相关阅读:
    类加载机制的学习4___类加载的过程
    类加载机制的学习3___自定义的类加载器
    类加载机制的学习2_____双亲委派模型
    使用.NET读取exchange邮件
    SSMS错误:A connection was successfully established with the server, but then an error occurred during the login process
    收缩数据库 DBCC SHRINKFILE
    How to: Change Sales Rep/Team via Mass Update
    Microsoft.Office.Interop.Word.Document.Open returns null on Windows Server 2008 R2
    设置文件夹的权限
    NetSuite API
  • 原文地址:https://www.cnblogs.com/kokoliu/p/916427.html
Copyright © 2011-2022 走看看