以服务器端为中心的 ASP.NET AJAX 模式 (Part 2 - Control)

来源:互联网 发布:如何发送淘宝商品链接 编辑:程序博客网 时间:2024/06/05 14:02

======================================================
注:本文源代码点此下载
======================================================

在上一篇文章当中,也就是《以服务器端为中心的 asp.net ajax 模式 (part 1 - behavior)》,我们探讨了较为易用的behavior模式。之所以说它较为易用,是因为它不涉及和原有page处理流程的交互,即使访问网络也是访问独立的web service(包括page上的[webmethod]),因此和page处理流程的设计绝对是正交的。但有时候我们需要的就是与page处理流程的交互,这时我们不得不使用与服务器端逻辑紧耦合的control了,这正是本次文章要讨论的内容。

在基本的asp.net ajax框架下,我们有三种方法来做基于control的ajax操作,它们分别是updatepanel、icallbackeventhandler和iscriptcontrol,下面我们就分别看看它们的特点和使用场景。

updatepanel

updatepanel是与服务器端逻辑进行交互的多种方案中最易用的一个,甚至就不能称之为交互——你根本就不需要触及任何客户端逻辑。一个服务器端操作,经过updatepanel的“劫持”,变成了一个客户端操作,而这个客户端操作又直接调用对应的服务器端操作,就这么简单。

如果用updatepanel来做一个带分支的选择对话框,那应该如何设计?思路可别跑到客户端的confirm方法上去,那可太绕了,或者说太不asp.net ajax了。用updatepanel,就应该坚持它的理念,一切客户端操作都是幻象,所有操作其实都是在服务器端进行的,包括选择对话框。要按asp.net的思路来做,我会做一个选择对话框控件,它的实质可能是一个浮动层模拟的对话框,这属于实现细节,我们不用太关注。重点是,这个选择对话框的分支逻辑是完全在服务器端进行的,async postback之后服务器端根据提交回来的数据决定如何触发事件。这样做整个分支选择的逻辑就是内嵌在page处理流程当中的,不需要通过cookies或者session来做数据的中转媒介,避免了page处理流程与更大作用域中的数据的紧耦合。

updatepanel适用于逻辑完全在服务器端的开发,并且我建议使用updatepanel时也就把所有逻辑放在服务器端,不要去写一些混合服务器端逻辑与客户端逻辑的代码。有人会说,你看老赵就很喜欢去动那个sys.net.webrequestexecutor来改变updatepanel的行为啊,但其实这属于分层设计思想中的一部分,他去动那个东西改变的也就是一个分层内的逻辑,只要层与层之间的接口不变,具体实现是可以按需设计的。但如果你用了updatepanel,同时又用cookies或者session来传值,这就跨越了n个层,增加了不少耦合度。

icallbackeventhandler

关于icallbackeventhandler,我已经说过无数次了,重点还是你必须用page处理流程来思考,只要你理解了page处理流程,你就明白为什么icallbackeventhandler在.net framework 2.0 beta2中只有一个方法,而到了rtm要分拆成两个方法。具体可以参考《asp.net 2.0 clientscript callback》,我就不再重复了。

如果用icallbackeventhandler实现一个带分支的选择对话框,又如何做?和使用updatepanel的做法类似,我还是会做一个选择对话框控件,并且这个控件继承自icallbackeventhandler。为这个控件编写javascript并实现icallbackeventhandler接口时,我会确保javascript对callback给出正确的调用参数,并在接口方法的实现中接收这些参数然后触发正确的事件,就这么简单。和updatepanel一样,不要偏离了icallbackeventhandler的设计思想,它的处理流程必须是合并到page处理流程中的,你的控件也就必须这样设计。

至于在什么情况下选择icallbackeventhandler?如果你有一个轻量级的ajax操作,但使用updatepanel更新整个区域的html开销很大的话,那么你可以考虑使用icallbackeventhandler。当然,前提是你懂得控件开发和javascript。

iscriptcontrol

这是最复杂的解决方案了,你需要实现一个control的两个副本——一个服务器端的,一个客户端的。有一部分逻辑,是要在客户端和服务器端重复实现两次的,而另外一部分逻辑,只需要在客户端或服务器端之中的一个实现一次。iscriptcontrol的经典例子,当然是asp.net ajax自带的timer控件。它的计时器是纯粹的客户端逻辑,然而tick事件却在服务器端触发,async postback成为了两者之间的桥梁。当然,就control本身而言,它并不在乎postback是不是异步的,tick事件只因postback而触发。

如果用iscriptcontrol来实现带分支的选择对话框,那将会和icallbackeventhandler的版本十分相似,唯一不同的地方就是它在客户端的逻辑会被封装为一个sys.ui.control的派生类,而icallbackeventhandler的客户端逻辑往往是不封装的。这样的好处显而易见,那就是代码更容易维护了,并且客户端的control可以同样可以加入事件支持,并提供和服务器端一样的代码分支事件。要知道在ctp阶段的timer控件,其客户端版本sys.timer(而非rtm的sys.ui._timer)是拥有tick事件的,和服务器端的tick事件对应,只不过rtm取消了此项功能,因为asp.net ajax 1.0的侧重点完全就是服务器端功能,客户端功能都被砍掉了。

什么情况下选用iscriptcontrol?如果你认为你的客户端逻辑应该封装为sys.ui.control的派生类,那就选择iscriptcontrol吧。

小结

我们分别讨论了三种通过control实现ajax调用的方案,并且一再强调了设计必须基于page处理流程,不要在此流程之外增加不必要的复杂度和耦合度。值得一提的是,有很多人质疑为什么要在web上提供这样一个支持分支的选择对话框功能,我的看法是这样的:既然客户端软件的流程会有此功能,那么web应用也有此功能就实在是太正常了,你删除blog post的时候问你一下是否确认删除,难道会有人觉得这个功能是设计错误?可能不同的只是表现形式而已,到底是confirm还是弹出层,甚至是一个专用的过渡页面。然而从用户体验的角度来说,这其实并不是最优的方案,多数时候用户删除就是确认删除,并不需要再问一次是否确认之类的愚蠢问题,但开发人员觉得用户错手删除的后果应当由用户自己承担,所以就做了这样一个对话框来推卸责任。真正好的用户体验是不需要确认的删除,但用户一定能够恢复,最好是按一下ctrl+z就可以了,然而对于开发人员来说还是有很多操作是无法做到可恢复的,这时候除了显示对话框也没有更好的解决方案了。

最后,如果你喜欢我的文章,可以通过订阅feed来及时获得更新:

cat in dotnet (feed)

cat in chinese (feed)


======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/
原创粉丝点击