为什么需要了解ASP.NET Core MVC的前世今生
我们就擦肩而过了
有趣
有用
有态度
ASP.NET Core MVC 是一个微软公司的web应用开发框架, 结合了MVC架构的高效简洁, 敏捷开发的思想和技术, 以及.NET平台最优秀的部分. 在这一章中, 你将了解到微软为什么要创建ASP.NET Core MVC, 将它和前辈以及替代品进行比较, 最后浏览ASP.NET Core MVC的新特性.
了解ASP.NET Core MVC的历史
最初的ASP.NET诞生于2002年, 当时微软想要保持传统的桌面应用开发的霸主地位, 将因特网视为潜在威胁. 图1-1展示了当时微软的技术栈.
ASP.NET Web Forms: 一组UI组件(如页面, 按钮等) 加上一个有状态的面向对象的GUI编程模型
ASP.NET: 一组在IIS中承载.NET应用程序的方法, 使用HTTP请求和响应进行交互
.NET: 一个多语言代码托管平台(当时是全新的, 本身就是一个里程碑)
ASP.NET Web Forms
微软使用Web Forms技术, 将用户界面(UI)建模为服务端控制的对象的层次结构, 来隐藏本身便具有无状态性的超文本传输协议(HTTP)和当时许多开发者不熟悉的超文本标记语言(HTML). 每个控件都在各个请求之间跟踪自己的状态, 在需要时将自己呈现为HTML, 并自动将客户端事件(如点击按钮)与相应的服务端事件处理程序连接起来. 事实上, Web Forms是一个巨大的抽象层, 用于在Web上呈现传统的事件驱动GUI.
这个想法基于一种让Web开发感觉和桌面应用开发相同的理念. 开发者可以从有状态的UI角度来思考, 不需要考虑一系列独立的HTTP请求和响应. 由此微软可以将Windows桌面开发大军无缝过渡到Web应用的新世界.
ASP.NET Web Forms 出了什么问题?
传统的ASP.NET Web Forms开发在理论上是好的, 但是实际情况要复杂得多:
视图状态(View State)负担: 在请求之间维护状态的机制(被称为视图状态, View State)导致服务端和客户端之间的大块数据传递, 即使在最平常的Web应用中也会达到几百KB的数据量. 并且这些数据在每个请求中都会跑一个来回, 导致响应变慢, 又增加了服务器的带宽占用.
页面生命周期: 将客户端事件连接到服务端事件处理程序代码的机制是页面生命周期的一部分, 很复杂也很脆弱. 基本没有开发者能在运行时成功操作控件的层级关系而不产生试图状态错误, 一些事件处理程序也会莫名其妙地失败.
错误的关注点分离: ASP.NET Web Forms的后端代码模型提供了从HTML标记中提取应用程序代码成为单独的后端类的方法, 以分离逻辑层和表现层. 但事实上, 开发人员更愿意在机型的后端类中将表现层代码(如操作服务器端的控件树)和逻辑层代码(如操作数据库数据)混合起来. 这最终导致了应用程序的脆弱和不智能.
对HTML的有限控制: 服务器端控件将自己渲染为HTML, 但不一定是你想要的HTML. 在ASP.NET的早期版本中, 输出的HTML不满足Web标准, 也不能很好的使用层叠样式表(CSS). 服务器端控件生成不可预知的复杂ID属性, 很难被JavaScript获取到. 这些问题在最近的Web Forms发行版中有所改善, 但仍然很难获取你所期望的HTML.
漏洞百出的抽象: Web Forms试图尽可能地隐藏HTML和HTTP. 当你尝试实现自定义的行为时, 经常会陷入抽象的泥潭中. 这迫使你对回传事件机制进行逆向工程, 或者执行迟钝的动作, 来生成想要的HTML.
可测试性差: Web Forms的设计者们当初并没有预料到自动测试会成为软件开发中至关重要的一部分. 他们设计的紧密耦合的架构不适合进行单元测试. 集成测试也很困难.
Web Forms并非一无是处. 微软在提高标准兼容性和简化开发过程上做了很大努力, 甚至将最初的ASP.NET MVC框架的一些特性应用到了Web Forms上. 当你想快速看到结果时选择Web Forms是很好的, 你可以在一个工作日内将一个相当复杂的Web应用程序运行起来. 但除非你在开发过程中足够仔细, 否则你会发现你创建的应用非常难以测试和维护.
最初的MVC框架
在2007年10月, 微软在现有的ASP.NET平台上发布了一个新的开发平台, 作为对对Web Forms的批评和竞争对手(如Ruby on Rails)的直接回应. 新平台被称为ASP.NET MVC框架, 反映了Web应用开发的新型趋势, 如HTML和CSS标准化, RESTful web服务, 游戏的单元测试, 和开发者应该拥抱HTTP的无状态本质的理念.
现在看来, 最初的MVC框架的基础理念是显而易见的, 但在2007年, .NET web开发的世界是缺少这些东西的. ASP.NET MVC框架的推出让微软的web开发平台重新走向现代.
MVC框架也标准了微软态度的重要转变, 它原本尝试控制web应用开发工具链的所有东西.
微软在MVC框架中采纳了新的理念, 如基于开源工具构建(如jQuery), 接受设计约定, 采用竞争对手(更成功的)的最佳实践, 并对开发者公布了MVC框架的源码.
最初的MVC框架出了什么问题?
在MVC框架初创时, 微软在现有的ASP.NET平台上构建是合理的, ASP.NET有很多可靠的底层功能, 为开发过程提供了一个良好的开端, 并已经被ASP.NET开发者所熟知.
但为了将MVC框架移植到最初为Web Forms设计的平台上, 需要作出妥协. MVC框架开发者逐渐习惯了使用配置文件和微调代码才能使应用程序正确运行, 尽管这些和他们的web应用毫无关系.
随着MVC框架越来越流行, 微软开始将一些核心特性加入到Web Forms, 结果越来越奇怪.
原本用于支持MVC框架的设计原则被扩展, 以支持Web Forms, 他们之间必须能够很好地融合. 同时, 微软开始扩展ASP.NET, 一般提供创建web服务(web api)和实时通讯(SignalR)的新框架. 每一个新框架都加入了自己的配置和开发约定, 都有自己的优点和古怪, 使得整个ASP.NET越来越混乱.
了解ASP.NET Core
在2015年, 微软宣布了ASP.NET和MVC框架的新方向, 最终产生了ASP.NET Core MVC, 本书的主要内容.
ASP.NET Core基于.NET Core上, .NET Core是.NET框架的跨平台版本. Windows仍然是一个占据统治地位的操作系统, 但承载在云端小容器中的web应用的份额正在增加. 通过采用跨平台的方法, 微软拓展了.NET的运用范围, 使ASP.NET Core应用程序在更广泛的载体上部署成为可能, 也让开发者可以在Linux或macOS上创建ASP.NET Core web应用程序.
ASP.NET Core是一个全新的框架. 它更简单, 更易用, 摆脱了Web Forms的传统. 而且因为它基于.NET Core, 支持在更多的平台和容器上开发web应用程序.
ASP.NET Core MVC在新的ASP.NET Core平台上提供了最初的ASP.NET MVC框架的功能. 它集成了先前的Web API的特性, 包括了一种更自然的生成复杂内容的方式, 并且使关键的开发任务(如单元测试)更简单可预测.
ASP.NET Core MVC 2中的新内容
ASP.NET Core MVC 2 发行版聚焦于整合早期版本中的一些工具和平台的更改. ASP.NET Core MVC 2需要.NET Core 2, 其扩充了许多API, 并支持更多的Linux发行版. 有用的更新包括一个简化了NuGet包管理的新的包管理系统, 一个新的ASP.NET Core配置系统, 以及对Entity Framework Core 2的支持. 最大的新特性是Razor Pages, 尝试用更现代的平台来重建Web页面的开发风格, 但MVC开发人员对Razor Pages并不感兴趣(我在书中也没有描述).
ASP.NET Core MVC的关键优势
接下来的章节简要的描述新的MVC平台如何超越传统的Web Forms和原始的MVC架构, 它又如何使ASP.NET重新回到前沿.
MVC架构
ASP.NET Core MVC遵循MVC模式, 它指导了ASP.NET web应用程序的形成和内部组件之间的交互.
区分MVC架构模式和ASP.NET Core MVC实现非常重要. MVC模式不是新鲜事物——可以追溯到1978年在Xerox PARC上的Smalltalk项目——但现在由于以下理由成为受欢迎的web应用设计模式:
MVC模式应用的UI遵循一个自然循环: 用户执行一个操作, 应用程序更改数据模型的状态并向用户更新视图作为响应, 然后再次执行此循环. 这可以很方便地适应传递一系列HTTP请求和响应的web应用程序
Web应用程序需要结合多种技术(例如数据库, HTML和可执行代码), 通常分为多层. 从这些层的组合中产生的模式可以很自然地映射到MVC模式的概念上.
ASP.NET Core MVC实现了MVC模式, 相较Web Forms在概念分离方面有极大的提升. 事实上, ASP.NET Core MVC实现了各种各样的特别适合Web应用程序的MVC模式.
可扩展性
ASP.NET Core和ASP.NET Core MVC是作为一系列具有良好定义的特性的独立组件构建的, 其实现.NET接口, 或者构建在抽象类上. 你可以轻松地将关键组件替换为自己实现的组件. 一般来说ASP.NET Core为每个组件提供了三个选项:
使用组件的默认实现(足够应对大多数应用程序)
使用默认实现的子类来调整其行为
使用接口或抽象基类的实现来完全替换组件
HTML和HTTP的严格控制
ASP.NET Core MVC提供了符合标准的HTML标记. 它内置的标记助手提供符合标准的输出, 和Web Forms相比有一个重大的改变. ASP.NET Core MVC鼓励使用CSS来设计简洁优雅的标记, 而不是生成一些几乎不受控制的HTML.
当然, 如果你想为复杂的UI元素(如日期选择器或级联菜单)添加一些现成的组件, ASP.NET Core MVC采用的”无特殊需求”方法使得引用一些单项优势(best-of-breed)的前端库(如jQuery, Angular, React或Bootstrap)很简单. ASP.NET Core MVC与这些库匹配得很好, 以致于微软专门创建了预包含它们的开发模版.
可测试性
ASP.NET Core MVC架构为应用程序的可维护性和可测试性提供了良好开端, 因为你可以自然地将不同的应用程序分成独立的部分. 另外, ASP.NET Core平台和MVC框架的每个部分都可以被隔离并进行单元测试. 可以使用任意的开源测试框架来进行单元测试.
在这本书中, 你会看到一些例子, 如何为ASP.NET MVC控制器编写简洁的单元测试, 如何使用各种策略以及进行模拟操作. 即使你从未写过单元测试, 也会有一个很好的开始.
可测试性不仅仅包含单元测试. ASP.NET Core MVC应用程序也可以和UI自动化测试工具一起工作. 你可以编写模拟用户交互的测试脚本, 而不需要猜测框架将生成那些HTML元素结构, CSS类或ID, 也不需要担心结构的意外变化.
强大的路由系统
由于web应用程序技术的发展, URL风格也发生了演变. 类似/App_v2/User/Page.aspx?action=show%20prop&prop_id=82742
的URL逐渐被简单的类似/to-rent/chicago/2303-silver-street
的URL取代.
关注URL结构的理由很多:
搜索引擎为URL中的关键字赋予权重. 搜索
rent in Chicago
更容易出现简单的URL许多网络用户已经足够了解URL, 并可以通过在浏览器的地址栏中输入URL来进行导航
当人们理解URL的含义时, 更容易点击它, 与朋友分享, 甚至在电话中朗读.
不会暴露应用程序的技术细节文件夹和文件名结构, 因此可以自由更改底层实现, 而不会破坏传入链接.
早期的框架很难实现干净的URL, 但ASP.NET Core MVC默认使用称为URL router
的功能来提供干净的URL. 这使你可以控制URL结构和应用程序的关系, 自由创建有意义的URL模式, 而不需要遵循预定义的模式. 当然, 这意味着你可以轻松地定义现代的REST风格URL结构.
现代的API
微软的.NET平台在每个发行版中不断发展, 支持甚至引领最新的现代编程趋势. ASP.NET Core MVC是为.NET Core构建的, 因此它的API可以充分利用C#开发者熟悉的语言特性, 包括await关键字, 扩展方法, lambda表达式, 匿名和动态类型, LINQ. 许多ASP.NET Core MVC API方法和编码模式比早期版本更清晰, 更具表现力. 如果你不熟悉最新的C#语言特性, 请不要担心, 我们在第四章中总结了MVC开发中最重要的C#特性.
跨平台
之前的ASP.NET版本局限于Windows平台, 需要在Windows桌面版上编写web应用, 并部署和运行在Windows server上. 微软让ASP.NET Core的开发和部署跨平台化了. .NET Core在不同平台都可以获取, 包括macOS和大量流行的Linux发行版. 跨平台支持使得ASP.NET Core应用更容易部署, 也很好地支持了应用容器平台, 如Docker.
现在大多数ASP.NET Core MVC开发都将是使用Visual Studio完成的, 但微软也创建了跨平台的开发工具Visual Studio Code, 意味着ASP.NET Core开发不局限于Windows了.
ASP.NET Core MVC是开源的
不像微软之前的web应用开发平台, 你可以免费下载ASP.NET Core和ASP.NET Core MVC的源码, 甚至编译自己定制的版本. 当你在调试系统组件并想逐步调试其代码(甚至阅读程序员的原始注释)时, 这是非常宝贵的. 如果你正在构建高级组件, 并希望了解存在哪些开发可能性, 或内置组件实际如何工作时, 也是很有用的. 你可以在https://github.com/aspnet
下载ASP.NET Core和ASP.NET Core MVC的源码.
总结
在这一章中, 我解释了ASP.NET Core MVC存在的背景, 和它从Web Forms和最初的ASP.NET MVC的演变. 我描述了使用ASP.NET Core MVC的好处和这本书的结构. 在下一章中, 你将看到ASP.NET Core MVC的一个简单示例, 来展示这些优越特性.