使用过.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
1
protected 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)
{
//什么都不做.
}
好了,总算完了,写了好久啊.
希望大家发表下看法.