摘要:
自从项目要求启用ajax之后,一直都很头痛,直到ComponentArt放出支持ms asp.net
ajax之后,所有的问题迎刃而解,于是乎立马down下ms asp.net ajax beta2,祭出神奇的UpdatePanel。但是正所谓“福之祸所依,祸兮福所至”,噩梦已经埋下伏笔......
一、噩梦的根源:庞大的页面
UpdatePanel在页面小的时候还是很好用的,而当页面控件数不断上升的时候,UpdatePanel就开始直线下降,我们现在页面有4,5百个控件,每做一次PostBack需要长达15秒钟之长,实在让人无法忍受。
二、救命稻草:ICallbackEventHandler
在实际应用中,我们很多页面同时也使用asp.net 2.0带的Callback机制,发现之间的速度差别不是一般大,那是相当的大阿。于是就萌发利用Callback的机制,制作一个替代UpdatePanel的框架。记得Teddy的AjaxHelper好像是基于Callback实现了,故下载了其框架的范例,发现和自己的想法还是有一定的出入,要直接转移到自己现有的Web框架来,改动量太大,所以,觉得自己写一个这样的框架会更好,不为重复发明轮子,而在于可以减少现有项目重构过程中的改动量。
三、CallbackPlus:
我把这个框架命名为:CallbackPlus,因为其完全是基于Callback机制来做的。
既然基于Callback机制,就有必要了解Callback的运行机制(详见Teddy的深度解析Asp.Net2.0中的Callback机制):
<script language="javascript" type="text/javascript"> |
function docallback(arg, context) |
{ |
<%= ClientScript.GetCallbackEventReference(this, "arg", "ReceiveServerData", "context")%>; |
} |
</script> |
<script type="text/javascript"> |
function ReceiveServerData(result, context) |
{ |
//TODO |
} |
</script> |
注册调用的script:docallback和接受的script:ReceiveServerData.
CallbackPlus原型就是这么的简单,它的即有功能也就是传递一个string参数,再返回一个string而已。
即然把CallbackPlus命名为一个框架,那似乎不该如此简陋吧,起码也应该把这些个手工注册的烦人工作进行下封装。或许有见过或者使用过Ajax.net的朋友都知道其异步事件的注册方法...嘿嘿,所谓大树底下好乘凉,我也没有必要自己寻找一个方式了,依葫芦画票也使用Attribute来实现(其实我已经深深的爱上了Attribute,哦也,反射,注入......,所有的实现一下子都变大那么的高雅迷人.)
server: |
[CallbackMethod] |
public void TestMethod1() |
{ |
//TODO: |
} |
client: |
<script> |
function doCallback(){ |
TestMethod1(); |
} |
</scipt> |
在这里通过CallbackMethod的标签将客户端的方法与服务端的方法一一映射起来。
四、Reflect,json让string插上梦想的翅膀:
这样子的功能,实在是不堪大用,只有进一步封装Callback的细节,才可以派上用场。而Callback的实现又是那么的简陋,简陋到只有一个接口ICallbackEventHandler两个方法
public string GetCallbackResult(); |
public void RaiseCallbackEvent(string eventArgument); |
而当string eventArgument 和return string这两段string结合reflect和json的时候,就可以发挥出不一般的作用。我们可以实现的目标:
- 让js的方法和cs的方法一一映射
- 让方法的参数和返回值也一一映射
- 让js的Object和cs的Class也一一映射
而实现这些的关键所在在于拦截docallback,ICallbackEventHandler的两个方法,ReceiveServerData的调用。关键的js代码:
<script type=\"text/javascript\"> |
var CallbackPlus = function(){ |
return{ |
DoCallback:function(target,arg,f,context){ |
WebForm_DoCallback(target,arg,f,context,null,true); |
}, |
OnCompleted:function(result,f){ |
var arguments; |
try{arguments = result.parseJSON();}catch(ex){arguments=result;}; |
if(arguments){ |
if(arguments[0]){alert(arguments[0]);}; " + |
if(arguments[1]){eval(arguments[1]);}; |
if(arguments[2]){ |
var obj; |
try{obj = arguments[2].parseJSON();}catch(ex){obj = arguments[2];} |
f.call(this,obj); |
}; |
}; |
} |
}; |
}();function onCompleted(){};</script> |
或许例子更能说明我的意图,请看Demo代码:CallbackPlusDemo.rar
五、后话:
当然这样子的js的取数将成为一个极大的工作量,但是可以在js写一个专门收集form数据的函数,这样子配合CallbackPlus则可实现完全自动的收集数据和更新数据。
目前框架刚刚投入使用,有兴趣的朋友不妨帮忙测试,发现bug希望可以通知我。谢谢
更新 07-01-09 22:10:
更正自己的一个观点:Callback无法取到控件的新的值。
仔细看了下Teddy中文章的讨论,发现Callback照样可以取到控件的新值,真是爽,项目的重构又少了点,不过又担心这个回传是不是会恢复到使用UpdatePanel时候的速度,看来还是需要大页面测试一下.修改CallbackMethod和js增加Postdata的控制设定
<script type=\"text/javascript\">
var CallbackPlus = function(){
return{
DoCallback:function(target,arg,f,context,isPostdata){
if(isPostdata){
__theFormPostData = \"\";
__theFormPostCollection = new Array();
WebForm_InitCallback();
}
WebForm_DoCallback(target,arg,f,context,null,true);
},
OnCompleted:function(result,f){
var arguments;
try{arguments = result.parseJSON();}catch(ex){arguments=result;};
if(arguments){
if(arguments[0]){alert(arguments[0]);};
if(arguments[1]){eval(arguments[1]);};
if(arguments[2]){
var obj;
try{obj = arguments[2].parseJSON();}catch(ex){obj = arguments[2];}
f.call(this,obj);
};
};
}
};
}();</script>
********************************************************************
*
版权声明
*
* 本文以Creative Commons的发布,请严格遵循该授权协议。
* 本文首发于博客园,
此声明为本文章中不可或缺的一部分。
* 作者网名: 浪子
* 作者EMAIL:dayichen
(at)163.com
* 作者BLOG: Http://Www.Cnblogs.Com/Walkingboy
*
********************************************************************
|