异步回调 之:客户端回调
对于数据量比较大的页面来说,频繁的整体刷新会降低性能以及客户的使用满意度。在客户端使用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", "")方法返回一个客户端函数的引用,通过这个方法从客户端调用服务器事件。该函数有多个重写函数,但最终都是调用方法
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
GetResultFromServe()接受服务器返回值,并进行客户端操作,如更新界面,从而实现无刷新更新。
服务器端
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
实现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 首先定义一个支持序列化的类
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
2 在服务期回调函数中生成Json字符串
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
当然,也可以生成一个XmlDocument对象,使用JavaScriptConvert.SericalizeXmlNode(XmlNode)方法转换Xml。转换后结果:{"FirstName":"Guo","LastName":"Lisa"}
3 客户端使用Json
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
这里要注意的是,由于从服务其传回来的值是字符串型,必须执行eval函数将字符串格式转换成json格式,否则无法通过“.”操作访问。对于xml数据,也通过同样的方式访问,唯一的不同的访问节点属性是要使用@,如json.user.@name。
回调深入分析
回调过程中Page的生命周期,如下图所示:
从上图可以看出,回调过程中并没有出现PreRender、Render事件,页面没有刷新显示。回调过程还可以访问VewState和PostBack Data,但不能保存。
回调是通过XmlHttp完成的,那么这些代码存在于页面的何处呢。查看页面源文件时,可以看到页面有一段脚本:
<script src="/TestWeb/WebResource.axd?d=d1AcIoQReWt2xvw-Cwrp0Q2&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