"似Ajax" 这就是说,你的应用程序是在Ajax概念提出之前就创建的。从客户端和服务器端的交互分析来说,你的客户端有大量的Javascript 代码接受XML数据,进行对象的序列化,然后使用Javascript配合其它的HTML技术展现这些对象和数据,也可能你还有一堆HTC或其它的Javascript的HTML表现层控件。你的服务器端是一个Facade(或者是Adapter,Observer)模式的(Handler)控制器,接收客户端Javascript的XML请求数据后,然后解析XML,然后调用相应的某个服务或业务组件,再将结果以XML的形式返回给客户端Javascript ,客户端的Javascript接收之后,再进行处理和显示,因为可以使用HTML的DOM 和CSS,所有页面的展现是动态的。
这样客户端是<Ajax in Action>中描述的Script-centric architecture 或Data-centric interactions 的方式。而且这种方式和Jesse James Garrett列举的Ajax 是最类似的,只不过那时你或我不知道这个可以叫Ajax,只不过是现在的人误解了Ajax,Ajax成了一种技术,一种特性,而首先不是一种某种架构下Web 应用了。
目前流行的Ajax-NET的框架基本上都没有实现双向序列化,因为实现一个TextBox的自动完成客户端只用接收数据就行了,根本不用传回数据/对象到服务器端,同样做一个Ajax的状态进度条也不用,但这些都是Ajax啊,我们衡量的标准是异步的、页面没有刷新。
1. MagicAjax.NET
这是目前框架中版本号最小的一个Ajax-NET实现,许多人很喜欢它,甚至一见如故,但真的看过它的代码之后,我有些担忧。
MagicAjax.NET基于这样一种策略,即__doPostBack 会提及整个的ASP.NET页面,这样会导致页面刷新,所以MagicAjax.NET使用AJAXCbo.DoPostCallBack 做局部的提交,而每个Ajax
Panel 中的内容则对应客户端即时的HTML内容,因为在MagicAjax.NET中,客户端只用执行eval(responseText) 服务器端Rendered返回的HTML就可以了(很被动)。
由于DoPostCallBack 会提交ViewState 以及AjaxPanelx$RBS_Store,几乎是用XMLHttpRequest 模拟一个正常的提交,所以服务器端可以创建页面的实例也可以根据ViewState 恢复所有的控件状态,同样AjaxPanel 以及AjaxControl 也都会实例化,然后接收客户端传来的_EventTarget, _EventArgument 走正常的ASP.NET控件的处理过程,等控件Rendered之后,最终的HTML输出被传回客户端,然后被客户端的eval 显示出来。
整个过程非常巧妙,这几乎是ASP.NET __doPostBack 的"Hook ASP.NET"版和加强版本。
而HttpModel 主要是为了解决Session和交叉提交,进行客户端Javascript的整理和注入,当然也是这里接收客户端的请求,在Application_EndRequest中返回结果。剩下的代码都是处理控件在VS Web Design中的设计时支持。AjaxCallObject.js 和WebParts.js 每次都要传到客户端。
MagicAjax.NET 的一些不足和想法:
1。 __doPostBack 的加强版,适合于ASP.NET的高级用户使用
2。由于和ASP.NET的页面处理机制依赖非常密切,控件的默认动作发生变化则可能不工作,比如第三方的某个自定义控件;
3。依赖ViewState ,如果是加密的ViewState,则可能工作不正常,我没有试,在代码中好像没有看见__VIEWSTATEENCRYPTED
4。是对ASP.NET 全部页面提交的优化,实现有限的Ajax功能,可扩展性不大
如果是基于ASP.NET 提供的控件和开发,那么MagicAjax.NET 是非常有效的,很好的解决了Session和跨页面状态的问题。而且客户端的操作和工作基本可以忽略,MagicAjax.NET设计贴近最近的ASP.NET的版本,目前不提供调用客户端直接调用页面的方法。但随着其发展,优势可能渐少,因为Atlas 最新的版本提供类似的UpdatePanel 控件。
2. Anthem.NET
目前是1.0版本,其设计理念是通过另外一个思路,遵循这样的理念--既然ASP.NET的各个标准控件没有实现提交功能,那么我可以产生一个提交的接口,然后继承原来的标准控件,然后再实现这个接口,这样每个控件都可以向服务器端单独进行提交。
每个控件的发生过程类似MagicAjax.NET,Anthem.NET提供了各个控件Javascript端的提交函数-这等于也截取了__doPostBack,之后Anthem.NET 还提供了完善的客户端的事件比如PostCallBack 和PreCallBack 这样的客户端事件,之后也将使用XMLHttpRequest 模拟一个传统的页面提交请求到服务器端,服务器端生成页面实例,这个过程和MagicAjax.NET一样,最后是将Rendered的HTML在控件的Render() 事件传回到客户端,客户端控件的innerHTML被赋值,动态更新
和MagicAjax.NET不同的是,Anthem.NET没有容器的概念,因为每个控件都增加了提交接口,所以可以单独的提交,所以单位是以一个控件为单位进行一次提交,Anthem.NET的花费更小些(但服务器端是类似的,因为整个ASP.NET页面的Pipeline都会进行)。
此外,Anthem.NET 还有另外的功能,就是可以通过客户端调用页面中的方法并获得结果/数据,这种情况下,你将调用Anthem_InvokePageMethod 方法,而不是Anthem.NET提供的默认各个控件的提交方法。这样Javascript的回调处理函数中的result.value 将可以获得调用的服务端的某个方法(该方法以[Anthem.Method]为标记)的执行结果,因为JavascriptPost的数据中有Page/MasterPage/Control 了,那么服务器端很容易通过这个标识获得方法的地址,应用反射寻找[Anthem.Method]标记,然后调用,将结果返回到客户端。
Anthem.NET支持返回对象,DataSet,DataTable和 WriteDataRow(WriteDataSet,WriteDataTable,WriteDataRow,WriteObject),返回的是符合是JSON规范的字符串,这样客户端的Javascript就可以使用这些对象了。不同于MagicAjax.NET,Anthem.NET 没有使用HTTP Model,所以结果是在页面的PreRender() 事件中处理和返回请求的结果。
2.1 Ajax.NET Professional
我没有看过Ajax.NET Professional 的源代码,但从例子中看得其支持调用页面的某个方法,以及返回对象,DataSet,DataTable的数据,我认为Ajax.NET Professional 的实现和Anthem.NET 原理是一样的,虽然Ajax.NET Professional 使用了HTTP Model,这个只是和Anthem.NET 一样,最终处理结果的返回处理上稍有不同不同。比较起来,Ajax.NET Professional 没有重新继承所有常用的ASP.NET控件实现部分提交的功能,所以可能Ajax.NET Professional 比较强项的是调用页面上的某个方法,并在客户端获得结果的数据,这个已经够实现大部分的Ajax的功能了。
从这个层面上看,我认为Ajax.NET Professional 是相对笨重和复杂了。Anthem.NET不使用HTTP Model,提供控件基本的局部提交,也提供数据层面的客户端方法调用。Ajax.NET Professional 的源代码似乎总是不想共享
这也就是我上面说的“似Ajax”架构,首先它是一个Web应用;它的表现层用DHTML+CSS + HTC控件+ Javascript ,服务器端用.NET或任何的服务器端技术,中间以XML方式序列化和反序列化进行传递数据。
简单的说,客户端需要将请求的数据封装成一个XML数据通过HTTP传递给服务器端,服务器端处理这个请求,并将结果也以XML的形式返回到客户端,客户端再处理这些请求,然后使用HTML+CSS进行展示。其实如果不是Web客户端(浏览器)的问题,这是最简单的架构,但关键问题在于上面我们说的Javascript端的对象封装成一个XML,以及到服务端解析XML变成服务器端对象,然后再将结果封装成XML,传回给客户端(Javascript),客户端也解析XML数据,然后变成Javascript 中的对象的这个序列化和反序列化的问题。另外一个问题就是表现层的展现问题,怎么展现,用什么控件?
所以,一个Ajax架构的Web应用程序,必须解决下面的问题:
1. 双向两路的序列化问题
2. 表现层展现的问题
3. 传输时客户端和服务器端的数据安全问题
4. 性能问题
5. 国际化支持
最好玩的双向两路的序列化问题,最早接触的是JSON ,它的问题在于扩展性,数据类型的支持和性能,但是平台无关性比较好,什么浏览器都可以,因为它不需要用msxml2.DOMDocumen分析XML,本质上就是用字符串描述对象;之后多平台的应用的迁移经历中(比如CORBAR,J2EE的后台应用),开始接触到XML-RPC ,ICE,Hessian,Web Services等等。其中XML-RPC有Javascript 的支持库,Web Services也有Javascript的支持库,也就是你可以使用Javascript访问或者获得XML-RPC/Web Services的对象,但是如果你将其作为一个主要的通讯协议,那么就会遇到另外一些问题,比如性能、国际化的问题,又会困扰你,XML-RPC和Web Services的一个主要问题都是性能,因为他们传输的XML大小都太大了,但显然用这些实现一个Ajax的特性,那是完全没有问题了。
比如,Atlas目前不也是使用一个Javascript库调用Web Services吗?,所以,你也可以这么做,同样你也可以用XML-RPC.NET 很快就可以实现一个Service,然后使用Scotandrew的XML-RPC javascript 库就可以在Javascript中发一个XML-RPC 消息请求这个服务,然后异步的获得这个结果,然后展现它。所以从技术的实现上讲,Ajax的特性非常容易实现,但从架构上来看。你需要思考更多的因素。当然直到最后,我们才发现,在项目中,最完美的方案是你自己写一个双向两路的序列化引擎供你的Javascript客户端使用。
这就说到了第二个问题,界面表现的问题,这个问题也是一个大的问题。这个问题一直会永远存在,Ajax之前没有人会太注意这些,但今天不同了,我想未来还会有很大的一个飞跃, Yahoo! 不是最近也开源了他的Yahoo! Web UI库,Atlas 也表示要提供更多的前端UI控件。无论如何,这个问题是,你的团队或组织是否有一套经过项目或客户检验的前端Javascript的库。无论是自己用Javascript写的也好,是自己写的一套HTC的控件库也好,总之这些是Ajax 架构中非常重要的一环。
Atlas 带来了另外一个思考问题,就是服务器端控件可能可以通过某种方式和Javascript的控件很好的集成在一起,以前我们用HTC解决了重用、性能、Behaviors、甚至模板功能。但是新的特性还是有比如数据的绑定、缓存和校验、甚至是数据编码和压缩、加密和解密,Javascript UI前端还是有许多可以做的,而且如何无缝的集成两者,这个有非常大的意义。
接着安全、性能、国际化等等,架构中的问题需要你依次考虑和解决,如果这么看Ajax,我认为,目前的Ajax框架还有很长很长一段路要走,同样真正完美支持Ajax架构的还需要继续努力。这些也是我在这篇专栏文章中的观点。
把这些合在一起,那么Ajax架构的开发包或框架,就应该是包含了上述几个问题(两路双向的序列化、Javascript UI 表现库、安全、国际化和性能等等)解决方案的一个平台实现。
同样也许你会说,不就是Ajax吗? 我干嘛要搞这么复杂,一定要搞到架构这个层面。
我认为,
第一,从架构的层面看Ajax,然后再应用相关的技术,比你直接使用某个Ajax框架然后再理解Ajax,你会从这个过程中收获更多。
第二,对于一个开发团队/组织来说,真正Ajax架构的产品,可以带来效益和具体的生产力。比如,我身边就有拥有这样的优势的团队,他们拥有一套统一的由Javascript+HTML+CSS+HTC的前端表现层,而后台的业务系统有两个平台,一个.NET平台和J2EE平台;同样我身边的也有这样的团队,他们拥有一套统一的由Javascript+DHTML+CSS+HTC+VML+ASP.NET的前端表现层,但他们的后台业务层分别来自.NET平台、J2EE平台和Unix平台,我不能说Ajax架构的应用似乎就是统一Web 表现层。因为从今天看到他们的明天,也许会是, 一个ASP.NET V2+Atlas 的统一表现层,一个统一CAB+Smart Client 的统一表现层,也可以是一个WPF 3D的统一表现层,也可以是一个Xgl 桌面的统一层。。。。
第三,从这架构的层面上,你也能够非常容易理解SOA或ESB概念,和SOA相比,Ajax架构的区别在于,Ajax有足够的松散耦合,但它依然以应用的数据为中心,更多的是一个面向Messages的架构,而且对于流行的WS-*协议的支持非常有限。
但是假如,今天你或你的团队已经有了一个Ajax 架构的应用,那么你是不是应该要小心选择现有的Ajax框架,因为这些Ajax的特性,相对于目前的架构来说,是多么小,但又可能会产生很大危害的一个因素。也许这样的团队并不多,也许也很多,但是只有我们从更高更深的层次来思考,那么我们就能做出正确的选择,并且从新的Ajax技术和研究中获得好处。
结论
当我们回到文章的起点,我希望这样能够说明的我观点,即Ajax-NET的框架或实现分为两类,一类是基于Ajax应用程序架构的,一类是基于Ajax特性的,目前几乎大部分的Ajax-NET的框架或实现都是基于Ajax特性,以Add-in 方式提供的代码或框架。
Ajax-NET的实现/框架选取上的建议:
· ASP.NET控件形式已经成为连接服务器和客户端Ajax通信的主要形式和选择。
· 客户端调用服务器端页面中的方法是Ajax的重要手段,使得客户端可以更加灵活的获得服务器端的数据。
· MagicAjax.NET,Anthem.NET用了"Hook ASP.NET"和Add-In的技术手段,使用上受到的影响比较多,这两个框架中,最简单的应用,第一选择MagicAjax.NET,但总是优先使用Anthem.NET
· 如果是自己写的服务器端控件,那么应该先掌握Anthem.NET的技术,然后使自己的控件拥有Ajax的特性
· MagicAjax.NET, Anthem.NET和wwHoverPanel 对于国际化的支持都有待加强
· 在Atlas没有正式发布之前,在ASP.NET的应用中优先在自己的项目中使用类似wwHoverPanel的技术,即尽可能的使用客户端回调功能,在特别需要的地方使用其方法调用的功能,充分发挥Ajax的特性,而不要因为Ajax而特意选择某个Ajax的框架
· Atlas的强项在于服务器端和客户端控件特性的集成、客户端的数据绑定、校验、内置的多个客户端Ajax 特性UI或组件,与ASP.NET的Profile, Membership ,Role 服务的集成,与Web Services和WCF 服务的集成,以及良好的国际化/开发工具支持的。因为它是一个完整的解决方案,所以最大的弱点是不能很容易地被老的Ajax架构的应用使用。另外该产品目前还在不断开发中,距离部署到生产环境中的要求还有差距。
· 轻量级的双向序列化可以考虑JSON格式,安全问题可以在传递的对象中增加字段,然后在服务器端进行校验。
· 对于原来已经有一套序列化框架的组织来说,其主要的目标是尽快将这个框架迁移/升级到ASP.NET V2,而不是优先考虑实现某个Ajax的特性
· Ajax 要求有足够的力量关注前端的UI展现或开发,所以对Ajax实现/框架的选择,最先要考察其客户端的实现以及提供的Web UI
看完这篇文章,我希望,2006年我们再谈起Ajax的时候,
· 作为技术人员,我不用谈论什么Web 2.0,我一样可以清楚的表达Ajax的概念
· 如果你是一个架构师,Ajax 不再是什么异步的XMLHTTP调用,不再是不刷新页面,它可以帮忙你Review应用程序的架构。
· 对于你的团队或老板来说,Ajax可以是你统一界面表现层的一个策略,同样也可能让你有了一个创建一套部门或公司级能够重用的UI类库的机会。
· 同样对于Javascript的开发人员来说,Ajax让你们还需要了解一些业务,并证明前台的Web开发人员一样很昂贵,后台开发也可以是技术含量不高的
· 对于SOA的爱好者来说,Ajax架构让你能够站在面向消息的架构和系统上来看面向服务;一般我们说,对内你首先要有一套面向消息的架构,然后对外你就很容易延伸成一个面向服务面向Internet的分布式架构。
· 最后,不要讨论Ajax的消亡,因为Ajax对于程序员来说,是一种力量均衡的策略,在Ajax中,Web前端的开发人员被重新重视,成为一支重要的力量。
后记
写这些文字的某几个段落,让我有些痛苦,因为我本来没想些这么多。所以你不要太在意我对各个框架的评价和描述,这些都是技术的层面的东西,其实我写这篇文字,主要是想突出Ajax的架构观,以及设计模式和Web应用架构重构的考虑,续而你也能够用类似横切面的角度,用Ajax来看你目前的应用和架构,从而更深的了解分布式对象的序列化、性能、安全以及Ajax 和ASP.NET服务器端控件的融合。最后欢迎大家斧正。
名词:
SOA = Service-Oriented Architectures
ESB = Enterprise Service Bus
Ajax-NET = .NET平台下的Ajax实现或框架
Ajax架构 = Ajax-Oriented Architectures
HTC = HTML Components
VML = Vector Markup Language
DHTML = Dynamic HTML
WPF = Windows Presentation Foundation
WCF = Windows Communication Foundation
Xgl = Xgl graphics subsystem(Novell )
JSON =JavaScript Object Notation
CAB = Composite UI Application Block