XinL

导航

异步回调 之:客户端回调

      对于数据量比较大的页面来说,频繁的整体刷新会降低性能以及客户的使用满意度。在客户端使用javascript通过XmlHttp方式调用服务器方法,能够避免在数据回送过程中引发的页面刷新,

      客户端回调是实现异步调用局部刷新的一个内置技术,通过简单步骤即可实现。主要在客户端和服务器端做以下操作:

      1 客户端:引发回调。向服务器传递参数,启动服务器函数的执行;接受服务器的返回值,修改客户端界面。
      2 服务器端:处理回调。接受客户端的回调参数;返回一个新的字符串值给客户端。

      回调示例代码

      客户端:

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    
<title>Untitled Page</title>
    
<script language=javascript>
        function button_click()
        
{
                          var args = document.forms[0]['TextBox1'].value;

                        
//CallBack(args,null);

                       <%= ClientScript.GetCallbackEventReference(this"args""GetResultFromServer""")%>
        }

        function GetResultFromServer(value, context)
        
{
            alert( value);
        }

    
</script>
</head>
<body>
    
<form id="form1" runat="server">
    
<div>
        Please input your name: 
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
        
<br />
        
<input id="Button2" type="button" value="Aysn Call" onclick="button_click()" />
        
<br />
        
<asp:Button ID="Button1" runat="server" Text="Server Button"/>
    
</div>
    
</form>
</body>
</html>

      button_click函数用于启动回调。必须使用html控件,不能使用Web服务器控件,否则肯定会引起一个新的http post请求,引起页面整体刷新。

      ClientScript是ClientScriptManager的一个实例,包含大多是客户端脚本函数。ClientScript.GetCallbackEventReference(this, "args", "GetResultFromServer", "")方法返回一个客户端函数的引用,通过这个方法从客户端调用服务器事件。该函数有多个重写函数,但最终都是调用方法

public string GetCallbackEventReference (
    
string target,                    //处理客户端回调的服务器 Control 的名称。该控件必须实现 ICallbackEventHandler 接口
    string argument,                //从客户端脚本传递给服务器端的一个参数
    string clientCallback,          //一个客户端事件处理程序的名称,该处理程序接收成功的服务器端事件的结果
    string context,                  //启动回调之前在客户端计算的客户端脚本。脚本的结果传回客户端事件处理程序。
    string clientErrorCallback,    //客户端事件处理程序的名称,该处理程序在服务器端事件处理程序出现错误时接收结果
    bool useAsync                  //true 表示同步执行回调;false 表示异步执行回调。
)
      最终生成的客户端脚本为:
function button_click()
{
    var args 
= document.forms[0]['TextBox1'].value;
    
//CallBack(args,null);
    WebForm_DoCallback('__Page',args,GetResultFromServer,"",null,false)
}

      GetResultFromServe()接受服务器返回值,并进行客户端操作,如更新界面,从而实现无刷新更新。      

      服务器端

public partial class Callback : System.Web.UI.Page,ICallbackEventHandler
{
    
private string _result;

    
protected void Page_Load(object sender, EventArgs e)
    
{
        
//string callRefreence = Page.ClientScript.GetCallbackEventReference(this, "arg", "GetResultFromServer", "context");

        
//string script = "function CallBack(arg,context){" + callRefreence + "}";

        
//Page.ClientScript.RegisterStartupScript(this.GetType(), "callback", script, true);
    }


    
public string GetCallbackResult()
    
{
        
return "Hello " + _result;
    }


    
public void RaiseCallbackEvent(string eventArgument)
    
{
        
if (string.IsNullOrEmpty(eventArgument))
            _result 
= "you input nothing";
        
else
            _result 
= eventArgument + ", we are from server" ;
    }

}

      实现ICallbackEventHandler,指示该控件能够作为服务器回调事件的目标控件。该接口提供两个方法:
      GetCallbackResult:将结果返回给客户端。返回结果只能是字符串格式,也可以返回Json字符串以方便客户端操作。
      RaiseCallbackResult:接受客户端参数,并处理服务器端事物逻辑。

      注:在button_click及Page_Load方法中,使用被注释的代码,执行效果相同。

      事件调用顺序是:button_click——〉RaiseCallbackEvent——〉GetCallbackResult——〉GetResultFromSever

      1 触发客户端回调事件(button_click)
      2 服务器端启动回调函数(RaiseCallbackEvent)
      3 服务器返回结果到客户端(RaiseCallbackEvent)
      4 客户端接受返回值(GetResultFromSever)
      5 局部刷新界面(GetResultFromSever里修改界面上控件的值)

      通过XmlHttp,从服务器端返回结果后回调客户端方法。当服务器方法执行完后,框架将通知客户端已经执行完毕,然后调用客户端函数(GetResultFromServer)

      返回Json值

      服务器返回给客户端的结果只能是字符串格式,但是字符串格式的变量处理起来不太方便,我们可以使用Json这一格式化的字符串以方便操作。使用Json功能需要下载Newtonsoft.Json.dll,用来生成Json串。dll文件中的JavaScriptConvert类支持Object对象和Xml对象与Json字符串之间的相互转换。 

      1 首先定义一个支持序列化的类     

[Serializable]
public class ObjWithCallBack
{
    
private string _firstName;
    
private string _lastName;

    
public string FirstName
    
{
        
get return _firstName; }
        
set { _firstName = value; }
    }


    
public string LastName
    
{
        
get return _lastName; }
        
set { _lastName = value; }
    }


    
public ObjWithCallBack()
    
{ }
}

      2 在服务期回调函数中生成Json字符串

    public void RaiseCallbackEvent(string eventArgument)
    
{
        ObjWithCallBack obj 
= new ObjWithCallBack();
        obj.FirstName 
= "Guo";
        obj.LastName 
= "Lisa";

        _result 
= JavaScriptConvert.SerializeObject(obj);
    }

      当然,也可以生成一个XmlDocument对象,使用JavaScriptConvert.SericalizeXmlNode(XmlNode)方法转换Xml。转换后结果:{"FirstName":"Guo","LastName":"Lisa"}

      3 客户端使用Json 

    function GetResultFromServer(value, context)
    
{
        eval(
" json = " + value );
        alert( json.FirstName 
+ "  " + json.LastName);
    }

      这里要注意的是,由于从服务其传回来的值是字符串型,必须执行eval函数将字符串格式转换成json格式,否则无法通过“.”操作访问。对于xml数据,也通过同样的方式访问,唯一的不同的访问节点属性是要使用@,如json.user.@name

      回调深入分析

      回调过程中Page的生命周期,如下图所示:

      从上图可以看出,回调过程中并没有出现PreRender、Render事件,页面没有刷新显示。回调过程还可以访问VewState和PostBack Data,但不能保存。

      回调是通过XmlHttp完成的,那么这些代码存在于页面的何处呢。查看页面源文件时,可以看到页面有一段脚本:
<script src="/TestWeb/WebResource.axd?d=d1AcIoQReWt2xvw-Cwrp0Q2&amp;t=633783538210457397" type="text/javascript"></script>

      通过浏览器可以打开此资源文件,该本件内容全部是javascript,包含了执行回调的所有客户端函数。

      局部刷新的详细原理解释,可参照http://www.cnblogs.com/liuxu-wxy/archive/2007/04/25/727346.html,目前自己还没弄明白

 

参考:
      http://www.cnblogs.com/liuxu-wxy/archive/2007/04/25/727346.html
      http://blog.csdn.net/cjqpc12345/archive/2006/08/07/1034759.aspx

posted on 2009-07-02 14:58  XinL  阅读(1118)  评论(0编辑  收藏  举报