上篇写道怎样用ASP.NET来实现页面的局部刷新,现在来说说它的实现机制。看下面的代码:
1
protected
void
Page_Load(
object
sender, EventArgs e)
2
{
3
txtTime.Value
=
DateTime.Now.ToString();
4
5
string
callBackRef
6
=
ClientScript.GetCallbackEventReference(
this
,
string
.Empty,
"
getTime
"
,
string
.Empty);
7
btnGetTime.Attributes[
"
onclick
"
]
=
callBackRef;
8
}
在page_load事件中,我们给按钮btnGetTime的onclick属性(事件)赋值。这个值是通过ClientScript获得的客户端CallBack函数引用。再看客户端生成的情况:
1
<
div
>
2
<
input
name
="txtTime"
type
="text"
id
="txtTime"
readonly
="readonly"
value
="2006-12-20 21:25:53"
/>
3
<
input
name
="btnGetTime"
type
="button"
id
="btnGetTime"
value
="Get"
4
onclick
="WebForm_DoCallback('__Page',"",getTime,"",null,false)"
/>
5
</
div
>
我们可以看到按钮btnGetTime的onclick事件将会调用WebForm_DoCallback函数。之所以把这篇文章放到AJAX分类中来就是因为这个函数了,现在看看这个函数是如何实现的:
1
var
__pendingCallbacks
=
new
Array();
2
var
__synchronousCallBackIndex
=
-
1
;
3
function
WebForm_DoCallback(eventTarget, eventArgument, eventCallback, context, errorCallback, useAsync)
{
4 var postData = __theFormPostData +
5 "__CALLBACKID=" + WebForm_EncodeCallback(eventTarget) +
6 "&__CALLBACKPARAM=" + WebForm_EncodeCallback(eventArgument);
7 if (theForm["__EVENTVALIDATION"]) {
8 postData += "&__EVENTVALIDATION=" + WebForm_EncodeCallback(theForm["__EVENTVALIDATION"].value);
9 }
10 var xmlRequest,e;
11 try {
12 xmlRequest = new XMLHttpRequest();
13 }
14 catch(e) {
15 try {
16 xmlRequest = new ActiveXObject("Microsoft.XMLHTTP");
17 }
18 catch(e) {
19 }
20 }
21 var setRequestHeaderMethodExists = true;
22 try {
23 setRequestHeaderMethodExists = (xmlRequest && xmlRequest.setRequestHeader);
24 }
25 catch(e) {}
26 var callback = new Object();
27 callback.eventCallback = eventCallback;
28 callback.context = context;
29 callback.errorCallback = errorCallback;
30 callback.async = useAsync;
31 var callbackIndex = WebForm_FillFirstAvailableSlot(__pendingCallbacks, callback);
32 if (!useAsync) {
33 if (__synchronousCallBackIndex != -1) {
34 __pendingCallbacks[__synchronousCallBackIndex] = null;
35 }
36 __synchronousCallBackIndex = callbackIndex;
37 }
38 if (setRequestHeaderMethodExists) {
39 xmlRequest.onreadystatechange = WebForm_CallbackComplete;
40 callback.xmlRequest = xmlRequest;
41 xmlRequest.open("POST", theForm.action, true);
42 xmlRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
43 xmlRequest.send(postData);
44 return;
45 }
46 callback.xmlRequest = new Object();
47 var callbackFrameID = "__CALLBACKFRAME" + callbackIndex;
48 var xmlRequestFrame = document.frames[callbackFrameID];
49 if (!xmlRequestFrame) {
50 xmlRequestFrame = document.createElement("IFRAME");
51 xmlRequestFrame.width = "1";
52 xmlRequestFrame.height = "1";
53 xmlRequestFrame.frameBorder = "0";
54 xmlRequestFrame.id = callbackFrameID;
55 xmlRequestFrame.name = callbackFrameID;
56 xmlRequestFrame.style.position = "absolute";
57 xmlRequestFrame.style.top = "-100px"
58 xmlRequestFrame.style.left = "-100px";
59 try {
60 if (callBackFrameUrl) {
61 xmlRequestFrame.src = callBackFrameUrl;
62 }
63 }
64 catch(e) {}
65 document.body.appendChild(xmlRequestFrame);
66 }
67 var interval = window.setInterval(function() {
68 xmlRequestFrame = document.frames[callbackFrameID];
69 if (xmlRequestFrame && xmlRequestFrame.document) {
70 window.clearInterval(interval);
71 xmlRequestFrame.document.write("");
72 xmlRequestFrame.document.close();
73 xmlRequestFrame.document.write('<html><body>' +
74 '<form method="post">' +
75 '<input type="hidden" name="__CALLBACKLOADSCRIPT" value="t">' +
76 '</form></body></html>');
77 xmlRequestFrame.document.close();
78 xmlRequestFrame.document.forms[0].action = theForm.action;
79 var count = __theFormPostCollection.length;
80 var element;
81 for (var i = 0; i < count; i++) {
82 element = __theFormPostCollection[i];
83 if (element) {
84 var fieldElement = xmlRequestFrame.document.createElement("INPUT");
85 fieldElement.type = "hidden";
86 fieldElement.name = element.name;
87 fieldElement.value = element.value;
88 xmlRequestFrame.document.forms[0].appendChild(fieldElement);
89 }
90 }
91 var callbackIdFieldElement = xmlRequestFrame.document.createElement("INPUT");
92 callbackIdFieldElement.type = "hidden";
93 callbackIdFieldElement.name = "__CALLBACKID";
94 callbackIdFieldElement.value = eventTarget;
95 xmlRequestFrame.document.forms[0].appendChild(callbackIdFieldElement);
96 var callbackParamFieldElement = xmlRequestFrame.document.createElement("INPUT");
97 callbackParamFieldElement.type = "hidden";
98 callbackParamFieldElement.name = "__CALLBACKPARAM";
99 callbackParamFieldElement.value = eventArgument;
100 xmlRequestFrame.document.forms[0].appendChild(callbackParamFieldElement);
101 if (theForm["__EVENTVALIDATION"]) {
102 var callbackValidationFieldElement = xmlRequestFrame.document.createElement("INPUT");
103 callbackValidationFieldElement.type = "hidden";
104 callbackValidationFieldElement.name = "__EVENTVALIDATION";
105 callbackValidationFieldElement.value = theForm["__EVENTVALIDATION"].value;
106 xmlRequestFrame.document.forms[0].appendChild(callbackValidationFieldElement);
107 }
108 var callbackIndexFieldElement = xmlRequestFrame.document.createElement("INPUT");
109 callbackIndexFieldElement.type = "hidden";
110 callbackIndexFieldElement.name = "__CALLBACKINDEX";
111 callbackIndexFieldElement.value = callbackIndex;
112 xmlRequestFrame.document.forms[0].appendChild(callbackIndexFieldElement);
113 xmlRequestFrame.document.forms[0].submit();
114 }
115 }, 10);
116}
这个代码着实有些长了,但是仔细观察4--44行,有些AJAX基础的人马上就能识别出这是使用XmlHttpRequest进行发送请求的,callback函数也设置为我们在page_load函数中设置为getTime。当服务器完成响应后,会回调getTime函数,将服务器返回的时间字符串设置到文本框中。
本文提供了一个非常简单的ASP.NET无刷新页面的实现,利用了ASP.NET原本就有的函数,这也进一步说明AJAX不是一个新的东西。本文提供的方法当然可以扩展到更广泛的应用中,利用服务器返回的字符串(可以是普通的字符串,当然也可以为作用更大的xml和html片断)动态的改变页面的局部区域。