为什么要坚持用ASP.NET MVC!(②)
尽管ASP.NET MVC架构和Web Form架构区别很大,但是还是有很多共同之处。毕竟它们都是以ASP.NET API与.NET框架为基础构建的。比较一下ASP.NET MVC和Web Form框架,以便知道有多少Web Form的概念与ASP.NET MVC开发相关。也许我们不知道,基于.NET平台开发网站的框架,实际上可以分成两个部分:可视化用户界面(Web Form)和后台Web组件(ASP.NET)。两者可以通过它们的命名空间区分开:所有System.Web.UI.*命名空间下的内容可以称为Web Form,而System.Web.*命名空间下的其他内容可以称为ASP.NET。与Web Form一样,ASP.NET MVC(所有类都在System.Web.Mvc命名空间下)也是基于ASP.NET平台构建的。所以两个平台可以十分相似,也可以完全不同,这取决于怎么看待这个问题。
HTTP处理程序和模块
大家应该对使用Visual Studio编辑ASP.NET MVC网站及其项目不会感到陌生,这和Web Form网站开发一样,都是基于.NET平台的应用程序。还可能要注意另外一些共享文件,比如web.config和Global.asax,它们在ASP.NET MVC 和 Web Form应用中起着重要作用。Web.config文件是一个XML文本文件,它用来储存ASP.NET Web应用程序的配置信息,而Global.asax 文件,又称为ASP.NET 应用程序文件,提供了一种在一个中心位置响应应用程序级或模块级事件的方法。ASP.NET MVC和Web Form共享的最著名的部分应该就是HTTP处理程序和模块(Handler and Modele)。虽然大部分Web Form API(System.Web.UI命名空间下)不会在ASP.NET MVC程序下运行,但是HTTP处理程序和模块确实是ASP.NET(System.Web)API的一部分,所以它们仍然会在ASP.NET MVC上下文里发挥作用。事实上,ASP.NET MVC管道本身正是从使用HTTP处理程序,处理外部请求开始的。
管理状态
管理状态即与用户相关的数据,在每个程序里都是个非常重要的内容,Web的无状态性导致Web应用程序中的管理状态数据变得相当复杂。为了处理管理状态这个问题,ASP.NET Web Form引入了“视图状态”的概念。每个请求的状态数据,在序列化之后会临时储存在页面的隐藏域控件里,随后的请求都会回传这些数据。视图是ASP.NET Web Form的重要部分,几乎每个页面和组件都会或多或少依赖于它。视图状态抽象也有它的缺陷,每个包含视图状态的请求必须以Form Post方式提交给服务器,而那些隐藏域的数据大小令人头疼:平时用不到,有时候却又非常大。最后它成为Web Form的性能瓶颈。
ASP.NET MVC具有完全不同的状态管理方法,它留给开发人员去实现。最重要的是,ASP.NET MVC完全抛弃了视图状态机制。除了视图状态,ASP.NET还提供了其他几种状态管理方法,同样可以在ASP.NET MVC里使用。例如,可以使用ASP.NET缓存和会话状态,或者HttpContext.Items API,这些可以帮助你在MVC应用程序里管理状态。
部署和运行时
ASP.NET MVC的产品环境部署和Web Form程序一样。这意味着之前学习的关于部署和维护ASP.NET程序的任何东西,比如IIS7、.NET应用程序池、跟踪、错误调试和部署程序集bin文件夹等,同样可以应用到ASP.NET MVC程序的部署中来。虽然ASP.NET MVC和Web Form程序采用了不同的架构,但是,从根本上说,两者都是部署并执行.NET代码来处理HTTP请求的。
#下表列出了ASP.NET MVC和Web Form的区别:
Web Form ASP.NET MVC
视图和逻辑紧密耦合 视图和逻辑被分离
页面(基于文件的URL) 控制器(基于路由的URL)
状态管理(视图) 无自动化的视图管理
Web Form语法 自定义语法(Razor)
服务器控件 HTML与CSS(JQuery)
母版页 布局
用户控件 部分视图
应用程序业务和视图分离:
ASP.NET MVC和Web Form最大的区别就是它们各自采用基础架构概念。例如,Web Form框架引入初期,就声称相比前任ASP框架能提供分离关注点的支持,ASP强制开发人员把业务逻辑和页面标记语言混合在单个页面里。WebForm框架不仅可以让业务逻辑和标记语言代码分离,还可以提供更强大的开发平台—.NET框架,可以基于此平台编写业务逻辑代码。但是,尽管Web Form框架相比传统的ASP框架更加先进,但是它依然关注于“网页”;虽然其代码可移植到别的地方,但是仍然很难做到业务逻辑代码和用户视图分离。
ASP.NET MVC通过集成松耦合组件来处理请求,构建于“分离关注点”概念之上。这个方法隔离了单个的组件开发,不仅有利于开发生命周期,更有利于组件的单元测试。同样,它也让动态处理请求更加方便。
URL和路由:
Web Form架构下,每个网站的URL由单个的物理文件.aspx表示,而且每个页面与单个页面类紧密耦合,页面无法动态选择自己绑定的类,代码隐藏类无法渲染别的视图。Web Form框架基于页面的请求处理方式与ASP.NET MVC的请求处理方式形成鲜明的对比:后者依赖于复杂的路由规则动态映射外部的URL到正确的控制器操作上,并允许操作动态指定要显示给用户的视图。
例如,请求处理管道在处理来自用户浏览器跳转到URL /auctions/details/123的结果和处理AJAX请求的结果可能不同,这是因为AJAX请求消息头里包含了一个标识AJAX请求的数据。用户直接访问URL时,服务器可能返回包含整个页面内容的HTML代码、JavaScript和CSS;而AJAX请求返回的只是Auction对象的序列化数据。此外,服务器可能选择不同的格式来序列化Auction对象,比如JSON或者XML,这些取决于请求要求的数据格式。Web Form框架本身并不支持这种动态处理请求的功能,需要借助HTTP处理程序和HTTP模块才能实现。
状态管理:
ASP.NET MVC和Web Form最具争议的区别也许就是它们如何跨请求处理用户的状态信息,特别是ASP.NET MVC抛弃了视图状态。为什么要删除这么重要的功能呢?简单地说就是ASP.NET MVC完全拥抱了Web标准的无状态的属性。为了更好地理解这种设计的初衷,我们先来回顾Web Form的历史。除了比ASP提供了更好的开发平台外,Web Form框架的另外一个特点就是引入了一种厚重的原生客户端应用开发技巧,比如“拖放控件”以及快速开发RAD的概念到Web开发中。为了体验原生客户端应用开发,Web Form必须在Web开发的基础概念如HTML标签以及CSS之上抽象出一层。原生应用程序开发中最重要的概念就是有状态的(stateful),这意味着应用知道交互的用户状态,并且可以在跨应用之间重用状态信息。Web是基于HTTP请求的,每个请求对应一个客户端请求和一个服务器应答。Web服务器必须分开处理每个请求,因此无法知道客户端请求的前后消息,这就让服务器和客户端无法进行有效的会话。为了在无状态的中介上实现有状态的交互,必须抽象出一层,这样,视图状态就诞生了。简单地说,视图状态序列化了客户端和服务端之间的交互状态信息,并把它们存储在每个页面的隐藏域里,随后发送给客户端。客户端需要在后续的请求中把这些会话状态信息传回给服务端。
MVC框架保留了Web无状态的本性,但并没有提供类似视图状态的机制,而是利用了缓存和会话状态。相反,ASP.NET MVC框架希望客户端请求包含所有需要的数据,以便于服务端处理它们。例如,ASP.NET MVC应答消息也许可以使用Auction的ID,而不是从数据库里查询出Auction数据后序列化整个对象发送给客户端,并在后续请求里再回传给整个对象。后续请求可以直接使用Auction的ID,ASP.NET MVC控制器可以使用它从数据库里查询Auction数据。显然,以上两种方法各有千秋。视图状态让客户端和服务端的交互更加简单,但是它包含的数据可能会变得臃肿,占用大量的带宽性能很差。换句话说,视图状态意味着开发人员可以省去很多麻烦,但会以占用带宽为代价。当然,如果开发人员不考虑每个页面的存储数据,则问题可能会变得更糟。ASP.NET MVC的方法可以从某种程度上削减页面内容,但是可能增加后台处理请求和数据库请求的成本,这也是MVC框架有待改进的地方。
布局与母版页:
最后,我们来看一下视图中最重要的、最基础的概念之一:布局(layout)。它可以定义页面结构以及网站主题,并且与所有的页面共享这个主题。这个概念类似于ASP.NET Web Form中的母版页(master page),在ASP.NET MVC框架中称之为布局。MVC布局可以让开发人员定义每个页面共享的HTML代码。与母版页一样,ASP.NET MVC布局允许开发人员指定多个内容块。与Web Form的内容页一样,ASP.NET MVC视图也可以指定想要在哪个视图里渲染。但有一个重要区别:对ASP.NET MVC管道来说,设置仅仅作为“推荐”,我们也可以随意修改视图的布局,包括删除或者完全使用无布局来渲染视图,比如在Ajax请求的情况下。
要点总结
如果你拥有多年的Web Form开发经验,那么学习ASP.NET MVC时可能也有障碍:除了它们的许多共同点和相似性之外,ASP.NET MVC和Web Form框架架构和设计目标在根本上是不同的。如果你习惯于“Web Form方式”,而且喜欢把这些方法用到ASP.NET MVC中来,那么可能会带来问题。正如之前介绍的“最重要的”和“危险的”的区别就是Web Form尽全力引入并维护视图状态,而MVC没有。从技术角度来说,这个问题就是从Web Form转向ASP.NET MVC开发时不再有视图状态,ASP.NET Web Form中大部分“状态性的”东西都不会再出现了。ASP.NET MVC的方式是通过一个临时媒介来存储这些数据,比如会话状态和应用程序缓存。
另一个编写代码时的最大区别就是Web Form依赖于服务器控件和用户控件,而MVC使用HTML和部分视图或第三方Jquery UI。使用Razor语法非常精简高效,替代ASPX视图引擎是很好的选择,也可以用Web Form语法开发MVC视图。这可以给Web Form开发者一个惊喜。