在许多时候,我们需要从客户端运行服务器代码而不执行回发,要实现这样的效果有非常多的方法,可以使用ASP.NET 中的 AJAX 功能,也可以使用象AjaxPro这样的第三方控件。这里我们要讨论的是使用Callback来实现AJAX。
要实现客户端回调的ASP.NET页的CS代码与创建ASP.NET页的过程类似,但也存在一些区别。该页的服务器代码必须:1、实现ICallbackEventHandler接口;2、提供RaiseCallbackEvent方法的实现;3、提供GetCallbackResult方法的实现。同时在客户端必须三个脚本函数:1、一个函数调用帮助器方法,该方法执行对服务器的实际请求;2、客户端回调函数,处理回调事件的服务器代码的结果调用并接收该结果;3、第三个函数是执行实际服务器请求的 Helper 函数。当在服务器代码中使用 GetCallbackEventReference方法生成对此函数的引用时,ASP.NET 将自动生成此函数。
现在,我们从实例来分析Callback的实现方法。
.aspx页源代码:
<!-- <br /> <br />Code highlighting produced by Actipro CodeHighlighter (freeware) <br />http://www.CodeHighlighter.com/ <br /> <br />-->
<%
@ Page Language
=
"
C#
"
AutoEventWireup
=
"
true
"
CodeFile
=
"
CallbackDemo.aspx.cs
"
Inherits
=
"
CallbackDemo
"
%>
<!
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
>
CallbackDemo
</
title
>
<
script type
=
"
text/javascript
"
>
function GetServerDateTime(context)
...
{
<%= ClientScript.GetCallbackEventReference(this, "", "ReceiveServerData", "")%>;
}
function ReceiveServerData(rValue)
...
{
document.getElementById("ResultsSpan").innerHTML = rValue;
}
</
script
>
</
head
>
<
body
>
<
form id
=
"
form1
"
runat
=
"
server
"
>
<
div
>
<
input id
=
"
btnSubmit
"
type
=
"
button
"
value
=
"
现在时间是
"
onclick
=
"
GetServerDateTime(ResultsSpan)
"
/>
<
br
/>
<
span id
=
"
ResultsSpan
"
runat
=
"
server
"
></
span
>
</
div
>
</
form
>
</
body
>
</
html
>
.aspx.cs源代码:
<!-- <br /> <br />Code highlighting produced by Actipro CodeHighlighter (freeware) <br />http://www.CodeHighlighter.com/ <br /> <br />-->
using
System;
using
System.Collections.Generic;
using
System.Web;
using
System.Web.UI;
using
System.Web.UI.WebControls;
public
partial
class
CallbackDemo : System.Web.UI.Page,ICallbackEventHandler
...
{
protected void Page_Load(object sender, EventArgs e)
...{
}
public void RaiseCallbackEvent(String eventArgument)
...{
}
public String GetCallbackResult()
...{
return DateTime.Now.ToString();
}
}
演示中客户端注册的脚本函数:<%= ClientScript.GetCallbackEventReference(this, "", "ReceiveServerData", "")%>;。这句动态生成一个客户端函数,该函数包含对来自GetCallbackEventReference方法的返回值的调用。ClientScriptManager.GetCallbackEventReference方法有4个重载函数,上面这个方法中,"this"是处理客户端回调的服务器控件,它必须实现ICallbackEventHandler 接口并提供RaiseCallbackEvent 方法,它的类型是System.Web.UI.Control。第二个参数是从客户端脚本传递给服务器的一个参数,它是String类型的。第三个函数是客户端事件处理程序的名称,它接收成功的服务器事件的结果,这里把回调结果返回给JS中的ReceiveServerData()方法。最后一个参数是启动回调之前在客户端计算的客户端脚本。脚本的结果传回客户端事件处理程序。
JS方法:
<!-- <br /> <br />Code highlighting produced by Actipro CodeHighlighter (freeware) <br />http://www.CodeHighlighter.com/ <br /> <br />-->
function
ReceiveServerData(rValue)
...
{
document.getElementById("ResultsSpan").innerHTML = rValue;
}
接收服务器事件的结果,并将结果呈现出来。
而服务器端的RaiseCallbackEvent()方法没有内容,因为这里是最简单的演示,我们没有回调参数,如果有回调参数在这个方法中处理。GetCallbackResult()则是返回当前的系统时间。
在VS中测试刚才的DEMO,发现会在浏览器源代码中自动生成一段这样的代码:
<!-- <br /> <br />Code highlighting produced by Actipro CodeHighlighter (freeware) <br />http://www.CodeHighlighter.com/ <br /> <br />-->
<
script
src
="/Callback/WebResource.axd?d=EsUKgUC2lEyf3iKipjXhYw2&t=633655516704843750"
type
="text/javascript"
></
script
>
这个DEMO产生的WebResource.axd有21KB大小,测试了一下,所有的文件都是一样的体积。它是在这个文件中创建了AJAX请求:
<!-- <br /> <br />Code highlighting produced by Actipro CodeHighlighter (freeware) <br />http://www.CodeHighlighter.com/ <br /> <br />-->
function
WebForm_DoCallback(eventTarget, eventArgument, eventCallback, context, errorCallback, useAsync)
...
{
var postData = __theFormPostData +
"__CALLBACKID=" + WebForm_EncodeCallback(eventTarget) +
"&__CALLBACKPARAM=" + WebForm_EncodeCallback(eventArgument);
if (theForm["__EVENTVALIDATION"]) ...{
postData += "&__EVENTVALIDATION=" + WebForm_EncodeCallback(theForm["__EVENTVALIDATION"].value);
}
var xmlRequest,e;
try ...{
xmlRequest = new XMLHttpRequest();
}
catch(e) ...{
try ...{
xmlRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
catch(e) ...{
}
}
var setRequestHeaderMethodExists = true;
try ...{
setRequestHeaderMethodExists = (xmlRequest && xmlRequest.setRequestHeader);
}
catch(e) ...{}
var callback = new Object();
callback.eventCallback = eventCallback;
callback.context = context;
callback.errorCallback = errorCallback;
callback.async = useAsync;
var callbackIndex = WebForm_FillFirstAvailableSlot(__pendingCallbacks, callback);
if (!useAsync) ...{
if (__synchronousCallBackIndex != -1) ...{
__pendingCallbacks[__synchronousCallBackIndex] = null;
}
__synchronousCallBackIndex = callbackIndex;
}
if (setRequestHeaderMethodExists) ...{
xmlRequest.onreadystatechange = WebForm_CallbackComplete;
callback.xmlRequest = xmlRequest;
xmlRequest.open("POST", theForm.action, true);
xmlRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
xmlRequest.send(postData);
return;
}
callback.xmlRequest = new Object();
var callbackFrameID = "__CALLBACKFRAME" + callbackIndex;
var xmlRequestFrame = document.frames[callbackFrameID];
if (!xmlRequestFrame) ...{
xmlRequestFrame = document.createElement("IFRAME");
xmlRequestFrame.width = "1";
xmlRequestFrame.height = "1";
xmlRequestFrame.frameBorder = "0";
xmlRequestFrame.id = callbackFrameID;
xmlRequestFrame.name = callbackFrameID;
xmlRequestFrame.style.position = "absolute";
xmlRequestFrame.style.top = "-100px"
xmlRequestFrame.style.left = "-100px";
try ...{
if (callBackFrameUrl) ...{
xmlRequestFrame.src = callBackFrameUrl;
}
}
catch(e) ...{}
document.body.appendChild(xmlRequestFrame);
}
var interval = window.setInterval(function() ...{
xmlRequestFrame = document.frames[callbackFrameID];
if (xmlRequestFrame && xmlRequestFrame.document) ...{
window.clearInterval(interval);
xmlRequestFrame.document.write("");
xmlRequestFrame.document.close();
xmlRequestFrame.document.write('<html><body><form method="post"><input type="hidden" name="__CALLBACKLOADSCRIPT" value="t"></form></body></html>');
xmlRequestFrame.document.close();
xmlRequestFrame.document.forms[0].action = theForm.action;
var count = __theFormPostCollection.length;
var element;
for (var i = 0; i < count; i++) ...{
element = __theFormPostCollection[i];
if (element) ...{
var fieldElement = xmlRequestFrame.document.createElement("INPUT");
fieldElement.type = "hidden";
fieldElement.name = element.name;
fieldElement.value = element.value;
xmlRequestFrame.document.forms[0].appendChild(fieldElement);
}
}
var callbackIdFieldElement = xmlRequestFrame.document.createElement("INPUT");
callbackIdFieldElement.type = "hidden";
callbackIdFieldElement.name = "__CALLBACKID";
callbackIdFieldElement.value = eventTarget;
xmlRequestFrame.document.forms[0].appendChild(callbackIdFieldElement);
var callbackParamFieldElement = xmlRequestFrame.document.createElement("INPUT");
callbackParamFieldElement.type = "hidden";
callbackParamFieldElement.name = "__CALLBACKPARAM";
callbackParamFieldElement.value = eventArgument;
xmlRequestFrame.document.forms[0].appendChild(callbackParamFieldElement);
if (theForm["__EVENTVALIDATION"]) ...{
</span
分享到:
评论