"Ajax" 这就是说,你的应用程序是在Ajax概念提出之前就创建的。从客户端和服务器端的交互分析来说,你的客户端有大量的Javascript 代码接受XML数据,进行对象的序列化,然后使用Javascript配合其它的HTML技术展现这些对象和数据,也可能你还有一堆HTC或其它的JavascriptHTML表现层控件。你的服务器端是一个Facade(或者是Adapter,Observer)模式的(Handler)控制器,接收客户端JavascriptXML请求数据后,然后解析XML,然后调用相应的某个服务或业务组件,再将结果以XML的形式返回给客户端Javascript ,客户端的Javascript接收之后,再进行处理和显示,因为可以使用HTMLDOM CSS,所有页面的展现是动态的。
这样客户端是<Ajax in Action>中描述的Script-centric architecture Data-centric interactions 的方式。而且这种方式和Jesse James Garrett列举Ajax 是最类似的,只不过那时你或我不知道这个可以叫Ajax,只不过是现在的人误解了AjaxAjax成了一种技术,一种特性,而首先不是一种某种架构下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.NETAnthem.NET提供了各个控件Javascript端的提交函数-这等于也截取了__doPostBack,之后Anthem.NET 还提供了完善的客户端的事件比如PostCallBack PreCallBack 这样的客户端事件,之后也将使用XMLHttpRequest 模拟一个传统的页面提交请求到服务器端,服务器端生成页面实例,这个过程和MagicAjax.NET一样,最后是将RenderedHTML在控件的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
支持返回对象,DataSetDataTable WriteDataRow(WriteDataSet,WriteDataTable,WriteDataRow,WriteObject),返回的是符合是JSON规范的字符串,这样客户端的Javascript就可以使用这些对象了。不同于MagicAjax.NETAnthem.NET 没有使用HTTP Model,所以结果是在页面的PreRender() 事件中处理和返回请求的结果。

2.1 Ajax.NET Professional
我没有看过Ajax.NET Professional 的源代码,但从例子中看得其支持调用页面的某个方法,以及返回对象,DataSetDataTable的数据,我认为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应用;它的表现层用DHTMLCSS 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,本质上就是用字符串描述对象;之后多平台的应用的迁移经历中(比如CORBARJ2EE的后台应用),开始接触到XML-RPC ICEHessianWeb Services等等。其中XML-RPCJavascript 支持库Web Services也有Javascript支持库,也就是你可以使用Javascript访问或者获得XMLRPC/Web Services的对象,但是如果你将其作为一个主要的通讯协议,那么就会遇到另外一些问题,比如性能、国际化的问题,又会困扰你,XML-RPCWeb Services的一个主要问题都是性能,因为他们传输的XML大小都太大了,但显然用这些实现一个Ajax的特性,那是完全没有问题了。

比如,Atlas目前不也是使用一个Javascript库调用Web Services吗?,所以,你也可以这么做,同样你也可以用XML-RPC.NET 很快就可以实现一个Service,然后使用ScotandrewXML-RPC javascript 库就可以在Javascript中发一个XML-RPC 消息请求这个服务,然后异步的获得这个结果,然后展现它。所以从技术的实现上讲,Ajax的特性非常容易实现,但从架构上来看。你需要思考更多的因素。当然直到最后,我们才发现,在项目中,最完美的方案是你自己写一个双向两路的序列化引擎供你的Javascript客户端使用。

这就说到了第二个问题,界面表现的问题,这个问题也是一个大的问题。这个问题一直会永远存在,Ajax之前没有人会太注意这些,但今天不同了,我想未来还会有很大的一个飞跃, Yahoo! 不是最近也开源了他的Yahoo! Web UIAtlas 也表示要提供更多的前端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+HTCVML+ASP.NET的前端表现层,但他们的后台业务层分别来自.NET平台、J2EE平台和Unix平台,我不能说Ajax架构的应用似乎就是统一Web 表现层。因为从今天看到他们的明天,也许会是, 一个ASP.NET V2+Atlas 的统一表现层,一个统一CAB+Smart Client 的统一表现层,也可以是一个WPF 3D的统一表现层,也可以是一个Xgl 桌面的统一层。。。。
第三,从这架构的层面上,你也能够非常容易理解SOAESB概念,和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.NETAnthem.NET用了"Hook ASP.NET"AddIn的技术手段,使用上受到的影响比较多,这两个框架中,最简单的应用,第一选择MagicAjax.NET,但总是优先使用Anthem.NET

·         如果是自己写的服务器端控件,那么应该先掌握Anthem.NET的技术,然后使自己的控件拥有Ajax的特性

·         MagicAjax.NET, Anthem.NETwwHoverPanel 对于国际化的支持都有待加强

·         Atlas没有正式发布之前,在ASP.NET的应用中优先在自己的项目中使用类似wwHoverPanel的技术,即尽可能的使用客户端回调功能,在特别需要的地方使用其方法调用的功能,充分发挥Ajax的特性,而不要因为Ajax而特意选择某个Ajax的框架

·         Atlas的强项在于服务器端和客户端控件特性的集成、客户端的数据绑定、校验、内置的多个客户端Ajax 特性UI或组件,与ASP.NETProfile, Membership ,Role 服务的集成,与Web ServicesWCF 服务的集成,以及良好的国际化/开发工具支持的。因为它是一个完整的解决方案,所以最大的弱点是不能很容易地被老的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

相关文章: