.NET Web ADF 的AJAX技术初探(script callback)
AJAX是实现部分页面刷新的一种技术。.NET Web ADF 中所有控件基本都实现了AJAX,并提供了一个callback result框架。Ajax 即”Asynchronous Javascript And XML”(异步 JavaScript 和 XML)。AJAX包含了以下技术:
(1)以XHTMI 和CSS 标准化呈现;
(2)DOM 动态显示和交互;
(3)用XML和XSLT 进行数据交换和操作;
(4)使用XMLHttpRequest 异步获取数据;
(5)最用JavaScript 将以上4 种技术串联在一起。
在ASP.NET 网页的默认模式下,当单击一个按钮或其他触发控件时,就向服务器发送一个请求,等服务器响应后,会重新创建一个新页及其控件,然后返回浏览器,这时,原本正在浏览的网页内容也将被更新。先看一个简单的例子。
1、在VS2010 新建一个Web Site,然后在Default.aspx 的设计视图里,将工具箱里ASP.NET 中的button 控件和TextBox 控件拉到页面,如图所示。双击button按钮,进人后台按钮click 事件代码的编写,在Button1_ Click 函数里,添加代码如下所示:
protected void Button1_Click(object sender, EventArgs e)
{
TextBox1.Text = "Hello World!";
}
添加完代码,按F5 进入调试。按下按钮之后,TextBox 相里出现“Hello World" 的瞬间,可以看到整个页面重新刷新了一遍,如图所示。
这种做法将浪费很多带宽,因为前后两个页面的大部分HTML代码是一样的。另外,用户需要等待服务器的响应,在服务器返回新页前,用户不能对其做一些操作。
与此不同,AJAX应用可以向服务器取回所请求的相应数据(或服务器响应结果),然后在客户端采用JavaScript进行处理,不用刷新整个页面而更新了用户所请求的内容。
Microsoft 为在.NET 环境下应用AJAX 提供了一个开发框架,即ASP.NET AJAX,这个框架支持一组新的服务器控件和API,这样,封装了AJAX的实现细节。我们在工具箱中可以看到,有一组AJAX Extensions 控件,其中包括ScriptManager 和UpdatePanel 等控件。只要通过添加ScriptManager 控件和UpdatePanel 控件,便可以让ASP.NET 页面支持AJAX功能,即无须刷新整个页面而实现部分页面更新。下面再看一个简单的例子,在上面的那个例子基础上修改的。
在Default.aspx 的设计页面添加ScriptManager 控件和UpdatePanel 控件,注意ScriptManager控件位置必须放在最前面,然后将button 控件和TextBox 控件剪切放在UPdatePanel 里面,如图所示。
Button1_ Click 函数不变,按F5 开始调试。按下按钮时,可以看到,整个页面没有刷新。一般地,Web ADF 也会用到这种模式。
2.script callback 解决方案
ArcGIS Server10.0 提供了两种AJAX 模式:一种是Script Callback (也叫Client Callback),另一种是Partial Postback.下面将通过一个例子介绍Script Callback模式。
使用Script Callback 这种AJAX模式,在服务器端上,需要在处理Callback 的类里实现ICallbackEventFHandler接口。这个接口提供了两个方法:
public void RaisecallbackEvent (String eventArgument)
public string GetCallbackResult ()
其中,RaisecallbackEvent 的参数eventArgument.是客户端传到服务器的参数,在RaisecallbackEvent 函数里面,可对该客户端传来的参数执行相应的处理。处理结果再通过GetCallbackResult 函数以string 格式返回客户端。这正是Callback 的运行机制。
那么,在客户端就需要一个触发函数,指定将要传到服务器的参数。同时,也需要一个处理函数,接收服务器传来的处理结果并作出响应,我们再看看客户端的javaScript(后面简称js) 代码。
<script language="javascript" type="text/javascript">
function getMessage() {
var message = 'getNumber';
var context = 'Page';
<%=sCallBackFunction%>
}
function processMyResult(returnmessage,context){
alert("Callback Result:" + returnmessage + ',' + context);
}
function postMyError(returnmessage,context){
alert("Callback Error:" + returnmessage + ',' + context);
}
</script>
getMaessage 这个函数便是触发回调的js 函数,其中最后一个语句非常重要,即 <%=sCallBackFunction%> < %=..% >是预编译句子,里面的内容将会在服务器执行。可将其比喻成导火线,通过这条导火线,引爆在服务器的“炸弹”,服务器的“炸弹” 即ICallbackEventHandler接口的那两个函数。对于sCallBackFunction这个变量,它是定义在服务器端里。然后在服务器端的Page- Load 事件中,调用GetCallbackResult的函数,并将其返回值赋给sCallBackFunction,代码如下:
sCallBackFunction = Page.ClientScript.GetCallbackEventReference(this,
"message", "processMyResult", "context", "postMyError",true);
GetCallbackEventReference这个方法有以下六个参数。
第一个: control 类型,实现ICallbackEventHandler的控件或Page.
第二个: string类型,是要传递到服务器端的值的变量名。在我们的例子中,message正是客户端的getMassage ()里的message 变量。
第三个:string 类型,是客户端接收服务器返回的CallbackResult并做相应处理的函数
的名称。
第四个:string类型,是客户端一变量名。如果有多个回调,则可以用该参数来区分。在本例子中,context就是客户端getMassage ()里的context变量。
第五个:string类型,是客户端处理回调失败时的函数的名称。
第六个:bool型,指定回调是否使用异步。若是,就设置为true。
其实GetCallbackEventReference函数也可以放在客户端的getMessage()函数里面,如下面代码所示,此时Page_Load事件中就可以不用调用此函数了。
function getMessage() {
var message = 'getNumber';
var context = 'Page';
<%=Page.ClientScript.GetCallbackEventReference(this,
"message", "processMyResult", "context", "postMyError",true)%>
}
我们再回到ICallbackEventHandler接口的两个函数,先看看服务器端的所有cs代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page,ICallbackEventHandler
{
public string sCallBackFunction;
protected void Page_Load(object sender, EventArgs e)
{
sCallBackFunction = Page.ClientScript.GetCallbackEventReference(this,
"message", "processMyResult", "context", "postMyError",true);
}
public string callbackResult;
#region ICallbackEventHandler Members
public string GetCallbackResult()
{
return callbackResult;
}
public void RaiseCallbackEvent(string eventArgument)
{
if (eventArgument == "getNumber")
{
callbackResult = "123456";
}
}
#endregion
}
我们要实现ICallbackEventHandler按口,需要在Default 的类头后面加上ICallbackEventHandler,添加后鼠标选中它,便在它下面出现一小横线,只要单击便出现一个框,如图所示。
任选择其中一项,后面就自动生成了GetCallbackResult 和RaiseCallbackEvent 这两函数。
前面提到,RaiseCallbackEvent 函数的参数eventArgument,是客户端传到服务器端的参数,实际上,它的值就等于js 函数getMessage里的message 变量,也就是说,客户端的getMessage()的message 变量的值,通过Page Load 事件中调用的GetCallbackEventReference 函数,传到了服务器端RaiseCallbackEvent 函数的eventArgument 参数,也就这样,服务器得到了客户端传来的值。
执行完RaiseCallbackEvent 函数,就开始执行GetCallbackResult 函数,将处理结果返回客户端。那么,处理结果CallbackResult 到底返回到客户端哪里? 前面已提到,客户端有这么个函数:
function processMyResult (returnmessage,context)
这个函数就是用来响应服务器传来的处理结果。实际上,CallbackResult 就是返回到这个函数的returnmessage 参数,即returnmessage 的值就等于GetCallbackResult 函数返回的值。而另外一个参数context,就是getMessage 函数的声明变量context.
接下来,在Default 页面上添加一个HTML 按钮控件(注意不要用ASP.NET 按钮控件),其HTML 代码如下:
<input id="Button1" type="button" value="button" onclick = "getMessage();" />
该按钮的单击事件,调用了客户端的getMessage () 函数。整个示例运行结果如图所示。
至此,实现了个间单的CallBack函数,
(1)单击按钮,调用客户端getMessage() 函数,从而触发回调,同时,把message传给服务器
(2) message 值传到服务器端RaiseCallbackEvent(string eventArgument)函数中的eventArgument,然后RaiseCallbackEvent利用eventArgument进行处理,并将结果以string型保存在callbackResult。
(3)处理好之后,交给GetCallbackResult(),由它将callbackResult返回客户端。
(4)客户端函数processMyResult(returnmessage,context)接收服务器返回callbackResult,其中returnmessage值就是callbackResult的值。Context不作任何处理,其值仍为getMessage()函数中context变量的值。
需要注意的是,这个过程中,客户端与服务器之间传递的值都为字符串类型。另外,客户端在请求时,实际上调用了底层一个WebForm_DoCallBack函数,再通过XMLHttpRequest 对象来向服务器发异步请求,从服务器获取数据,最后用javascript和DOM来更新页面。WebForm_DoCallBack函数包含于ASP.NET System.Web.dll中,对AJAX一些实现细节进行了封装。
参考资料:【1】马林兵,WebGIS技术原理与应用开发(第二版).科学出版社
地理信息科学
Writed By NX
QQ:1051926720