在.NET的ASPX页面中,通过实现ICallbackEventHandler接口,可以实现与前台的JavaScript进行交互,同时页面也不会进行刷新操作。可以肯定的是通过Ajax实现的。但是怎么样验证我的想法呢。今天将生成的页面源代码分析了一下,看出了实现的过程了。
首先,按照通常的实现方式,下面以一个验证用户名的例子来做一个分析。例子的过程是如果填写的用户名是juelance,那么就代表用户名已经被占用了。
前台的代码:
<!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></title> <script type="text/javascript"> function result(val) { alert(val); } </script> </head> <body> <form id="form1" runat="server"> <div> <input id="Text1" type="text" /> <input id="Button1" type="button" value="检查是否被占用" onclick="CheckUserName()" /> </div> </form> </body> </html>
后台代码:
string _arg = string.Empty; protected void Page_Load(object sender, EventArgs e) { string callbackfunc = ClientScript.GetCallbackEventReference(this, "val", "result", null); string raisefunc = "<script type='text/javascript'>\nfunction CheckUserName(){ \nvar username=document.getElementById('Text1'); \nvar val=username.value;\n" + callbackfunc + " \n}\n</script>"; ClientScript.RegisterClientScriptBlock(this.GetType(), "CheckUserName", raisefunc); } public string GetCallbackResult() { return _arg; } public void RaiseCallbackEvent(string eventArgument) { if (eventArgument.ToLower() == "juelance") { _arg = "已经占用"; } else { _arg = "可以使用"; } }
通过浏览此页面,查看页面源文件,找出关键的五处代码:
第一段<script type="text/javascript"> function result(val) { alert(val); } </script>
第二段<script type='text/javascript'> function CheckUserName(){ var username=document.getElementById('Text1'); var val=username.value; WebForm_DoCallback('__Page',val,result,null,null,false) } </script>
第三段<div> <input id="Text1" type="text" /> <input id="Button1" type="button" value="检查是否被占用" onclick="CheckUserName()" /> </div>
第四段<script type="text/javascript"> //<![CDATA[ WebForm_InitCallback();//]]> </script>
第五段<script src="/fileupload/WebResource.axd?d=9Tb_MUlmMDCcCyQuK_rG4FhymHvBLwJp4n0GFDh7eDHQ-LQWHqbCW2mQbjFZuz21VVpqY7H9UUGQdR-NlAisCjFvrHQ1&t=634209066757546466" type="text/javascript"></script>
关键是第二段中WebForm_DoCallback方法,这个js方法是从那里来的呢?浏览最后一段js指向的src,来看看,在文件中查找这个方法,可以看到定义如下:
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"]) { var callbackValidationFieldElement = xmlRequestFrame.document.createElement("INPUT"); callbackValidationFieldElement.type = "hidden"; callbackValidationFieldElement.name = "__EVENTVALIDATION"; callbackValidationFieldElement.value = theForm["__EVENTVALIDATION"].value; xmlRequestFrame.document.forms[0].appendChild(callbackValidationFieldElement); } var callbackIndexFieldElement = xmlRequestFrame.document.createElement("INPUT"); callbackIndexFieldElement.type = "hidden"; callbackIndexFieldElement.name = "__CALLBACKINDEX"; callbackIndexFieldElement.value = callbackIndex; xmlRequestFrame.document.forms[0].appendChild(callbackIndexFieldElement); xmlRequestFrame.document.forms[0].submit(); } }, 10); }
在这段代码中与我需求相关的代码:
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; }
大致的原理是:通过一个Ajax请求,将客户端的方法发送到服务器,服务器执行完相关的方法后,再调用客户端的result方法,并将服务器中产生的结果传入,最后执行客户端的JavaScript方法。这样就完成了整个回调事件的过程。