使用过.net中的局部刷新功能兄弟都知道,据我的认识,最用的是微软自己提供的和第三方提供组件.微软的提供的方法有两种,一种是VS2005提供的UpdatePanel组件,把updatepanel拖进页面,然后要进行局部刷新的内容(如gridview),只要在updatepanel这个容器里的控件都可以做到局部刷新;第二种方法是VS2003中就有的,即让页面的后代码类实现ICallbackEventHandler接口,该接口有两个方法,RaiseCallbackEvent方法用于客户端处理传过来请求,其中参数是客户端传过来的(JS),GetCallbackResult(没有参数)用于服务器端返回给客户端的结果(text或XML),另外在Page_Load还必须向客户端注册向调用服务器端的脚本,客户端调用这个脚本中函数得到响应数据,具体的细节在这里就多讲了.第三方组件,我知道Ajaxpro,偶没用过.另外,不管是微软提供的还是第三方的方法,我注意到,在运行时向页面注册一些资源文件(js),即一些函数.当然单独注册在页面的也有.
在使用微软的方法实现局部刷新时,我发现一个问题,如果一个页面加载的数据量(2000条记录)很大时,我要刷新的局部数据量很少,只有数据库中的一条记录.异步刷新的速度很慢,和页面加载的数据量成正比,即页面数据量越大,本身整个页面加载的时间就越慢,而局部刷新也会越慢.这不是我们要的局部刷新吧.
仔细看了ajax组件生成的资源文件,仔细看了下代码,大概地了解了,当页面做异步请求时(通过XMLHttpRequest对象),它把请求对象指向了本身即,请求的url是页面中Form的action的值,而Post对参数呢,应该是form里所有的表单字段,所以post的数据量就该不会少,另外,在服务器执行的时候,页面要模拟正常情况执行一遍(这里包括PageLoad方法),然后把再响应的数据丢给XMLHttpRequest,我有一点不明白的是,微软的这种异步请求,是把部分数据还是所有数据丢给XMLHttpRequest对象呢,还有就是在客户端怎么处理返回的数据.
我有一点可以肯定的,页面把正常时操作的流程全走了一遍,如果页面数据量大的话,则会把这些数据再读一遍.而这也许是我们所不需要的.
讲了这么多,看看我的方法,有点老土,用原始的ajax操作来完成.
基本的原理:在客户端,建立XMLHttpRequest对象,请求的对象也是页面本身.传的参数是请求用到的参数,应该很少吧,其中包括一个ajax请求的标识符;建立两个函数于,用于执行请求成功和失败后的操作.在服务器端,需要在两个地方进行操作,一个是Page_Load方法,一个是页面被重写了的OnPreRender方法.前者是在判断有ajax请求的参数时,立即返回,不执行pageload包括的其它代码,OnPreRender用于输出,即返回给XMLHttpRequest的字符串.
具体我将用代码做解释,如下:
客户端用到的代码:
1.Ajax请求函数:
Ajax
1//建XMLHttpRequest对象,适应于firefox,ie
2 if(typeof XMLHttpRequest=="undefined" && window.ActiveXObject)
3 {
4 function XMLHttpRequest()
5 {
6 var arrSign=["MSXML2.XMLHTTP.5.0","MSXML2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"];
7 for (var i=0;i<arrSign.length;i++)
8 {
9 try{
10 var oRequest=new ActiveXObject(arrSign[i]);
11 return oRequest;
12 }
13 catch(oError)
14 {}
15 }
16 throw new Error("MSXML is not installed");
17 }
18 }
19 //Complete是请求时执行的函数,fail是失败时执行
20 function request(url,Param,Complete,fail,Method,isAsnc)
21 {
22 var oRequest=new XMLHttpRequest();
23 if(!Method) Method="post";
24 if(!isAsnc) isAsnc=false;
25 oRequest.open(Method,url,isAsnc);
26 oRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
27 oRequest.onreadystatechange=function()
28 {
29 if(oRequest.readyState==4)
30 {
31 //alert(oRequest.ResponseText);
32 if(oRequest.status==200)
33 {
34
35 if(typeof(Complete)=="function")
36 {
37 Complete(oRequest);
38 }
39 }
40 else
41 if(typeof(fail)=="function") fail(oRequest);
42 }
43
44 }//
45 oRequest.send(Param);
46 }
2.以下是前台页面的用到函数.
FrontPage
1 <script type="text/javascript" language=javascript src="js/include.js"></script>
2 <script type="text/javascript" language=javascript>
3 if(typeof($)!="function")
4 {
5 function $(id)
6 {
7 return document.getElementById(id);
8 }
9 }
10 //fpDetail 是页面中一个div的id,页面中某个地方将调用cc()这个方法
11 function cc(para)
12 {
13 var pars="callback=1¶="+para;
14 request($("<%=form1.ClientID%>").action,pars,showResponse,showAlert,null,true);
15 return false;
16 }
17 function showResponse(originalRequest)
18 {
19 $("fpDetail").innerHTML=originalRequest.responseText;
20 }
21 function showAlert(request)
22 {
23 alert("Some Error appear!\r\n"+request.statusText);
24 }
25 </script>
3.后代码文件,主要包括page_load里的操作和OnPreRender里的操作.
Page_Load
1 protected void Page_Load(object sender, EventArgs e)
2 {
3 string callBack;
4 callBack = Request.Form["callback"];
5 if (callBack != null && callBack == "1")
6 {
7 return;
8 }
9 Button1.Attributes.Add("onclick", "return cc();");
10 .
11 .
12 .
13 .
14 .//其它操作
15 }
OnPreReender
1protected override void OnPreRender(EventArgs e)
2 {
3 //gv1是一个GridView对象
4 string callBack;
5 callBack=Request.Form["callback"];
6 if (callBack != null && callBack == "1")
7 {
8 Response.Clear();
9 //GYF.ExecuteQuery返回一个Datatable
10 gv1.DataSource = GYF.ExecuteQuery("sql语句");
11 gv1.DataBind();
12 StringBuilder sb = new StringBuilder();
13 gv1.RenderControl(new HtmlTextWriter(new StringWriter(sb)));
14 Response.Write(sb.ToString());
15 Response.End();
16 }
17 else
18 base.OnPreRender(e);
19 }
最后,需要注意的是,.net在ajax请求时会验证服务器端控件,如Gridview导出excel时,ajax这种请求可能使得一些服务器控件没有在前端呈现,以致于通不过页面验证,这里可以做如下修正:
1.前端页面中<%page%>中加入 EnableEventValidation=False;
2.重写页面的方法VerifyRenderingInServerForm方法
public override void VerifyRenderingInServerForm(Control control)
{
//什么都不做.
}
好了,总算完了,写了好久啊.
希望大家发表下看法.