ASP.NET发展史([译])
Part I
0、摘要:
ASP.NET的第一个版本发布于20年前,这些年来,可以看到ASP.NET团队在过去的几年里对网络上发生的重大变化作出的建设性的改变。最初,ASP.NET是一个封闭的平台,试图隐藏和抽象Web。如今ASP.NET已经蜕变成一个开源和跨平台的平台——它完全领会了Web的本质。
这是ASP.NET历史的3篇系列文章的第一部分。涵盖从ASP.NET最初版本到最新的ASP.NET Core。
ASP.NET的第一个版本发布于20年前的2002年初,是.NET框架1.0版本的一部分。它最初的设计目的是提供一个比Classic ASP和ActiveX更好的Web平台,一个对现有Windows开发人员来说比较熟悉的Web平台。
当我们回顾它早期的设计,可能会惊讶地看到MVC、Web Services、JSON或JavaScript类型等概念是如何被考虑、讨论和/或引入ASP.NET的,这个时间比你记忆中的时间段更早。
我希望你会享受回忆过去,就像我写它时的心情一样。
1、ASP.NET Web Forms时代(2002-2008)
微软在2002年1月向全世界发布了 ASP.NET 作为.NET 框架1.0版本的一部分。那时XML才是王道,未来是基于 XML Web 服务的。
当时 ASP.NET 的程序经理 Rob Howard
"在过去的几个月中,业界已经意识到 Web 服务的前景。我有没有提到 XMLWebServices 代表了微软.NET 策略,是 ASP.NET 的一个核心特性吗?"
在 XML 时代,微软并不羞于在 XML 数据孤岛或 XMLHTTP ActiveX 控件等领域推进 IE。几乎没有人预料到其他浏览器会将后者作为标准的 XMLHttpRequest API 来实现,而且它将成为所谓的 Asynchronous JavaScript and XML(AJAX)的基础。当然,浏览器标准只是一个梦想,像 JavaScript 这样用浏览器检测技术来支持多浏览器的技术得到了
这些年也是DHTML(Dynamic HTML)迅速发展与推广的年代(在被标准化的 DOM、 JavaScript 和 CSS 淘汰之前)。用于创建桌面应用程序的企业开发人员正越来越多地转向 Web 应用程序,这些应用程序通常部署在企业内网上。
就在那时,微软发布了.NET 框架1.0以及 Visual Studio.NET,其中 ASP.NET Web Forms 是包的核心部分。这给了微软平台的开发人员一个比以前Classic ASP、 ActiveX 控件和 VB6 DLL 混合体更好的构建 Web 应用程序的方法。
2、Web Forms的设计
千禧年之交,微软开辟了几条重要的战线:
-
它对Java的拥抱、扩展和消灭策略失败了(
-
它需要一个更好的解决方案来构建和托管Windows中的Web应用程序,这样它才能在互联网泡沫的背景下继续竞争。
-
它的 RAD (Rapid Application Development快速应用开发)平台,老旧的 VisualBasic6,需要一个替代品。围绕开发人员的可视化工具和设计人员产生了许多议论,这是开发人员生产力的新银弹。
为了克服这些挑战,微软最终提出了自己的管理和解释平台.NET 框架,以及 C # 和 VB.NET 语言(现在简称为 Visual Basic)。这个框架的1.0版本提供了用于桌面和 Web 开发的特定工具,命名为 Win Forms 和 ASP.NET Web Forms。正如我们将看到的那样,他们的桌面和 Web 框架名称的相似性并非巧合!
Win Forms 被设计成用于开发 Windows 桌面应用程序的 VB6的继承者,为 Visual Studio 中的表单设计器提供了 VB6开发人员所熟悉的 RAD 体验。.NET Web Forms 将为开发 Web 应用程序提供非常类似的体验,在 Visual Studio 中有一个类似的表单设计器,并且编程模型将真正与他们现有的桌面开发人员产生共鸣。它的名字也暗示了这个新框架是Classic ASP 脚本框架的继承者。
VisualStudio2003中的 Web 窗体设计器
这在当时是不可思议的,并且使得习惯于 Windows 应用程序的开发人员更加顺利地过渡到Web开发。或者至少在纸面上,因为这只能通过一些巧妙的抽象来实现,而这些抽象恰恰是构建 Web Forms 框架的基础,这些抽象将隐藏 Web 的真实性,并最终导致向 MVC 的转变!
Web Forms 是按照
每个 Web 表单都有两个不同的部分。最终定义页面 HTML 的 aspx 模板,以及实现 Page Controller 并提供必要逻辑的类。
这是 HelloWorld.aspx 模板:
<%
注意:虽然 aspx 文件中使用的视图引擎允许在<% %> 块中混合代码,但是这是不可接受的。.NET 社区刚刚摆脱了Classic ASP 及其意大利面条式的代码问题!
及其相应的代码隐藏 HelloWorld.aspx.cs 文件:
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
public class HelloWorldPage: System.Web.UI.Page
{
protected System.Web.UI.WebControls.TextBox name;
protected System.Web.UI.WebControls.Button MyButton;
protected System.Web.UI.HtmlControls.HtmlGenericControl mySpan;
public void SubmitBtn_Click(Object sender, EventArgs e)
{
mySpan.InnerHtml = "Hello, " + name.Text + ".";
}
}
ASP.NET 框架提供了一组可以在每个页面上使用的控件。
asp:TextBox 和 asp: Button 标记是服务器控件的示例,它们不是标准的 HTML 标记。发送到客户端的最终 HTML 和 JavaScript 是在呈现页面时由框架生成的,并且取决于页面的属性和潜在的客户端。它们中的每一个都得到一个添加到代码隐藏类中的变量。
还有 HTML 服务器控件,它们与 HTML 元素直接相关,其目的是让代码隐藏类可以访问它们。在前面的示例中有一个 span mySpan,其对应的变量是 code-behind 类。
示例中的 asp: Button显示了另一个有趣的特征。服务器控件可以呈现必要的 HTML 和 JavaScript 来通过 PostBack 请求处理服务器上的事件,这只不过是对同一页面的 POST 请求,以及当前状态和被触发的控件和事件的名称。代码隐藏类中的一个方法可以与这些事件各自关联,这样在处理 PostBack 请求期间就可以在服务器上执行事件对应的方法。与 SubmitBtn _ Click 方法关联的 MyButton 的click 事件就是一个例子。
如你所见,每个页面都包含
对于习惯于使用桌面应用程序的开发人员来说,这个模型很熟悉,因为在桌面应用程序中,视图和页面控制器作为相同过程的一部分运行。然而,它向他们隐瞒了一个事实,即客户端和服务器是通过一个网络分离的,本质是无状态的。
ASP.NET通过组合拳保存状态:
-
它的状态管理,结合了不同的保存数据的方法。除了通常的Application和Session State,ASP.NET引入了View State。在将页面HTML发送到浏览器之前,服务器将页面控件的状态编码到Base64编码的字符串中,该字符串作为隐藏的表单字段包含在内。这个隐藏字段将被浏览器自动包含在POST请求中。
-
一个包含事件的页面生命周期,框架将在处理请求期间的不同时刻自动调用这些事件。这将允许从头初始化页面状态(如从数据库获取)或从发布的View State复原状态(如表单控件的属性)
下图显示了这一流程的运作情况:
ASP.NET 1.0中典型页面的流程
框架的设计假设大部分工作将由服务器完成,客户机主要呈现 HTML 文档并发出新的 GET/POST 请求。这是一个时代的标志,因为那时的客户端不像今天这样强大,浏览器也不像今天这样先进。
总的来说,ASP.NET 成功地实现了它的目标,提供了一个更接近桌面开发的模型和一个用于 Web 开发的 RAD 平台。然而,它在无状态网络上的有状态模型结合了对开发者隐藏Web的抽象,最终损害了框架的长远发展。
当然,自从 ASP.NET 发布以来的这些年我们有了当时人们没有的洞察力,批评或嘲笑20年前做的事情是很容易的。
但是,你会对 ASP.NET 中可能实现的功能感到惊讶!
通过阅读微软的模式和实践团队在2003年6月提供的模式,我发现它特别有趣,所有这些模式都是在 ASP.NET 中实现的:
-
他们提供了
-
-
的确,大多数开发人员从未遵循过这些模式。是的,指导主要集中在 RAD 方面,以及通过拖放设计器上的控件和在代码隐藏中编写事件处理程序来构建简单方便的应用程序。
但是,正如我们在这些模式中所看到的,开发人员只要稍微努力一下就可以构建干净的应用程序,这也是事实!
在我们继续之前,让我们回想一下在那个时候Web开发世界都发生了什么。
-
ASP.NET的主要外部竞争对手是
-
如前所述,一般的XML和基于XML的Web Services在当时是一个宏伟的设计。ASP.NET有一个通过HTTP提供的
-
微软仍然拥有大量的VB6、ActiveX和Classic ASP程序员,他们必须转移到新的.NET平台上。正如你想象的那样,大量的工具以及文档被制作出来帮助过渡,就像这一
公平地说,ASP.NET 的引入对微软来说是一个巨大的成功。它成为了主要的 Web 开发平台之一,并且在企业界得到了广泛的应用。
3、完善ASP.NET Web Forms
尽管它很成功,但NET 框架还处于起步阶段,亟待成熟和完善。微软采用了每两年发布一次主要新框架版本的时间表,框架所有的部分包括 ASP.NET 都在同一时间进行升级。
2003年.NET Framework 1.1发布了,ASP.NET 收到了移动控件和其他一些小更新。2005年的.NET Framework 2.0框架向前迈进了一大步,走向成熟。
在那一刻.NET 获得了一些最有用和被广泛采用的特性。回首往事,想象自己在写作.NET 代码,而不使用泛型或可空值类型那种感觉真是太奇妙了。让我们简要回顾一下其中的一些特性:
-
泛型类型的引入使得采用提高可重用性和类型安全性的模式成为可能,比如泛型集合。在泛型之前,运行时强制转换通常会导致异常,并且由于值类型的装箱/拆箱而导致性能损失。微软自己会在框架的许多领域添加泛型方法和类型
-
还引入了可空类型,因此现在可以在使用Nullable<T>结构(泛型类型的另一个例子)时将null赋值给值类型
-
C#获得了对静态类的支持。没错,C#在第一个版本中没有静态类!
-
现在C#和VB.NET中都可以使用部分类。这将极大地帮助Win Forms和Web Forms将Visual Studio生成的设计器代码与用户编写的实际代码分离开来。
-
一种用于管理事务的新模型,它能够透明地在现有环境事务中获取事务,并在本地事务管理器和Microsoft分布式事务协调器(Microsoft Distributed transaction Coordinator, MSDTC)之间进行提升。这极大地造福了许多使用ADO.NET用于数据访问和/或与现有的COM+组件集成的人。
在专门研究 ASP.NET 2.0时,2.0版本的重要性更加明显。除了受益于新的.NET 特性,比如泛型,ASP.NET经历了一次重大的变革,成为了一个更强大、更易于使用的框架。
这个版本中包含了一个新服务器控件的长列表。事实上,控件成为社区中扩展 ASP.NET 的首选方式之一,并开启了第三方控件供应商的行业。
但是包含更多的控件并不是框架更新的所有内容。
框架还有许多其他的补充和改进,改变了开发体验:
-
View State得到了改进并缩小了大小,这是对ASP.NET的一个批评(最开始View State太大了)。引入“控件状态”的概念是为了将控件发挥作用(不能禁用)所需的绝对最小数据与视图状态的其余部分分离开来
-
在引入母版页(Master Pages)之后,实现一致的外观和感觉变得更容易了,母版页的概念接近于ASP.NET MVC与ASP.NET Core中看到的布局。整个网站的样式可以通过主题Themes和皮肤Skins集中起来,主题由许多CSS和皮肤(.Skin)文件组成,皮肤SKin是CSS的XML文件,可以为ASP.NET服务器控件设置属性
-
现在可以创建站点地图(Site Map)了,这是一个描述网站中页面位置和名称的xml文件。该文件可以直接与新添加的用于导航目的的服务器控件一起使用,能够从站点地图呈现面包屑、菜单或树菜单。
-
页面生命周期使用了新的事件
-
现在允许跨页回发。也就是说,一个页面现在可以将POST发送到另一个页面,而不仅仅是发送到它自己
-
缓存特性得到了显著改进。基于SQL server的新依赖被引入,开发人员现在可以编写他们自己的缓存依赖实现,缓存页面中也允许动态部分(即动态字段也允许页面缓存)
-
Web部件允许用户对网站进行个性化设置,就像iGoogle或My Yahoo!时间的传送门。服务器控件可以用作Web部件(并且可以创建自定义部件),用户可以从门户类页面中添加、删除和自定义这些Web部件
-
最后,将工厂设计模式与泛型相结合,以创建所谓的提供者模式(Providers模式)。这只是一个与ASP.NET脱钩的契约。从底层数据的实际来源获取成员资格或概要文件等特性。该框架已经包含了典型源(如SQL Server或XML)的提供者,而开发人员可以创建自己的提供者。然后可以将它们作为提供者配置部分的一部分连接到它们的特性上。
我相信即使只有上面这样一个简短的总结,您也会同意我的观点,即 ASP.NET 2.0总体上是向前迈出的重要一步
然而,您可能已经注意到,对于客户端来说,几乎没有什么新东西。大多数新功能仍然面向服务器,浏览器主要专注于呈现服务器上生成的页面。
这一切即将改变,而且会很快发生!
4、JavaScript 和 AJAX 的重要性
Web 2.0引入了对更多动态网站的需求,越来越需要利用客户端脚本。这种趋势一直持续到2010年前5年,直到这些功能成为现代网站的一个共同特征和预期特征,尤其是在谷歌产品采用了这些功能之后,这种趋势开始进入指数增长。2005年初创造的术语 AJAX (Asynchronous JavaScript and XML)迅速成为一个流行词,无处不在,并成为 Web 开发中的下一个大事件。
在 ASP.NET 2.0之前,AJAX 这个术语还没有被创造出来,也没有被采用,但是它所依赖的 XMLHttpRequest API 已经在浏览器中使用了好几年了。事实上,没有什么能真正阻止 ASP.NET 开发人员创建服务器端端点,然后从 JavaScript 调用这些端点,正如
ASP.NET 2.0认识到 JavaScript 与 XMLHttpRequest 交互的重要性与日俱增(仍然没有通常标识为 AJAX) ,并引入了一个称为
在 ASP.NET 2.0即将发布的时候,AJAX 的狂热已经开始了。微软已经注意到并
Atlas 最终在2007年1月以微软 AJAX 1.0的形式发布。除了将 AJAX 带到了 ASP.NET 的前沿,这次发布标志着 ASP.NET 的两个有趣的第一次:
-
它是独立于.NET框架发布的,作为一个独立的安装程序,将Microsoft AJAX添加到ASP.NET 2.0。在此之前,开发人员必须等待.NET框架2年的发布周期才能获得新特性
-
AJAX控件工具包的新控件部分的源代码是开源的,可以在CodePlex中获得。客户端JavaScript代码是在MS-PL(微软公共许可证)下发布的,它类似于MIT许可证。服务器端代码使用了更严格的MS-RsL (Microsoft Reference Source License),目的是促进开发和调试。
微软的 AJAX 关注点并不局限于 AJAX 请求,而是集中在当时现代动态网站所需的所有客户端方面:
-
-
像
-
引入了一个完整的
-
ASMX和WCF
虽然微软 AJAX 的工作接近其初始版本,NET Framework 3.0于2006年11月发布。这个版本的唯一目的是介绍基于 XML 的框架 WCF (Windows Communication Foundation)、 WPF (Windows PresentationFoundation)和 WF (Windows Workflow Foundation)。
直到一年后.NET Framework 3.5于2007年11月发布,ASP.NET 获得了新的特性。最重要的一点是,Microsoft AJAX 现在是框架的一部分。另一个主要特性是包含 ListView 控件,它允许通过定制不同的模板,轻松地为任何数据源构建类似 CRUD 的功能。
我们也不应该忘记.NET 3.5引入了 LINQ (语言集成查询) 这一点,这让包括 ASP.NET 开发人员在内的许多人感到高兴,他们甚至获得了一个特定的 LinqDataSource 控件。
5、结论
在2007年年底,我们有了一个经过3次重大修订的成熟的.NET 框架,其中包括一个非常强大的 ASP.NET 框架。然而,弊端开始显现。ASP.NET 提供的抽象在不需要深入理解 HTML、 HTTP 和 JavaScript的情况下提供的客户端功能方面做得相当不错,但是当事情不能正常工作时,或者需要定制功能时,同样的抽象就会泄露出来并成为阻碍。
通过绑定关注服务器端控件和声明性编程,对开发者隐藏了更多的Web网络现实。当开发人员试图跟上对 Web 应用程序日益增长的期望时,他们会发现自己在围绕框架工作,而不是按照框架预期的方式工作。
与此同时,对于开发者和网络用户来说,事情开始发生变化。Ruby on Rails 于2004年发布,对 Web 开发世界产生了巨大的影响。它的方法与 ASP.NET 有很大的不同,它提供了一个轻量级的 MVC 框架,该框架接受 Web 的优点和局限性,并且明确地试图不妨碍开发人员的工作。相比之下,它使 ASP.NET 看起来又老又重,受到那些寻求更好的 Web 应用开发方法的人的批评,并经常被作为反例。
然而,最大的变化是由第一代 iPhone 引起的。在2007年夏天推出,一旦移动设备的用户数量爆炸式增长,网络将不再是原来的样子!
Part II
0、摘要
第1部分概述了ASP.NET的初始设计以及微软如何对Web Dev的各种变化做出反应。在第二部分中,我们将看看这些变化是如何影响ASP.NET MVC的发展的,最终使ASP.NET转变成一个由多个库组成、可以解决不同问题的更灵活的框架。
.NET 的第一个版本于20年前的2002年初作为.NET 架构的一部分发布。在本系列文章的第一部分中,我们看了它的初始设计,一个提供了比Classic ASP 和 ActiveX 更好的Web 平台,一个对现有的 Windows 开发人员来说熟悉的平台。
随着Web成为最快节奏的平台之一,回顾过去,我们会发现框架别无选择,只能适应自最初发布以来发生在Web及其周围技术上的多种变化。当然,这在当时的变化中并不明显!
在本系列的第二部分中,我们将看看这些变化是如何影响ASP.NET MVC的开发,最终将ASP.NET转变成一个更灵活的框架,该框架由多个库组成,可以解决不同的问题。
1、MVC-新方向(2008-2014)
网络的变化发生得很快,ASP.NET 对此有些准备不足。我们已经讨论过Web表单的抽象意味着Web的现实以及HTTP、HTML和JavaScript是如何对开发人员隐藏的。尽管 ASP.NET 在2002年以服务器为中心的 Web 应用程序和基于 XML 的 Web Services服务的旧世界中运行良好,但 Web 开发的进步使这种抽象变得更加漏洞百出。
一方面,越来越多的功能使用JavaScript 代码实现移动到客户端。尽管 ASP.NET 拥有针对 JavaScript 的工具,特别是当微软的 AJAX 成为框架的一部分时,但是它的重点仍然主要放在控件上。
使用 ScriptManager 编写 JavaScript 并将其添加到页面是可能的,但是要绕过 PostBack 模型并不容易,除非使用 ASMX 或 WCF 服务构建 SPA 应用程序,而 JavaScript 还没有为此做好充分准备。也可以将
最终,许多开发人员主要使用 UpdatePanel 之类的控件,以及 AJAX Control Toolkit 的控件/扩展程序部分,而不是编写 JavaScript。
另一方面,JSON 成为 AJAX 请求最常用的有效负载格式,因为它比XML更小,而且易于与通常使用它们的 JavaScript 代码集成。ASP.NET 和 WCF 都专注于基于 XML 的 SOAP 服务,后来增加了对HTTP上的JSON的支持。ASMX Web 服务和 WCF 服务都需要专门配置来处理基于 HTTP 的 JSON。
但这还不是全部。
由于 Web Forms 为 ASP.NET 开发人员抽象了Web,直接使用 JSON 在没有框架中的一流支持的情况下是
总之,当 Ruby on Rails 这样的框架爆发时,我们有一个漏洞百出的 Web Forms 抽象,同时 JavaScript 和 JSON 的重要性日益增加。
2、引入ASP.NET MVC
微软意识到了这种情况,在
-
遵循
-
授予对生成的HTML的完全控制
-
为TDD提供一级支持(
-
与现有ASP.NET基础设施集成(缓存、会话、模块、处理程序、IIS主机等)
-
可插拔。提供适当的hooks钩子,以便像控制器工厂或视图引擎这样的组件可以被替换
-
默认使用ASPX视图引擎(没有视图状态或回发),但允许使用其他视图引擎,如来自MonoRail的视图引擎等。
-
支持IoC(
-
提供对URL和导航的完全控制
值得强调的是,这并不是第一次尝试一个更清洁的 .NET Web 框架。我们已经看到,早在2003年,微软自己就为 MVC 或Front Controller(前端控制器)等模式的实现提供了指导。那个.NET 社区也致力于提供自己的替代方案,其中 MonoRail (
用 Steve Naidamast 的话说:
"MVC 作为一种模式已经存在很长时间了,.NET 社区也有类似的“Castle 项目”,被称为“ MonoRail”。在微软开始推广他们自己的 MVC 版本之前,它从来没有被任何人认为是实质性的东西,这个版本看起来和“Castle项目”的人们已经开发的一模一样。"
最终,该框架的1.0版于2009年3月发布。它独立于.NET 框架,发布周期为2年。它的代码可以在 CodePlex 中获得,并使用 MS-PL 许可证,拥有修改和重新发布代码的广泛权利。这标志着微软对开放源码态度的一个重要里程碑。
开发者现在有了来自微软的另一种选择,它拥抱网络,不试图隐藏HTML、HTTP、JavaScript或其无状态特性等细节。相反,它提供了与它们一起工作所需的工具和灵活性。
HTTP请求现在将由Controller类的特定Action方法提供服务。URL通过一个新的路由模块匹配到控制器和动作,该模块允许使用默认/controller/action的基于约定的路由。然后,操作方法将执行服务请求所需的必要逻辑并返回操作结果,其中呈现视图只是结果之一。视图将是位于与控制器不同文件夹中的ASPX模板。
ASP.NET MVC 应用程序的请求生命周期
通常的 Hello World 示例可以包含位于 Controller 文件夹中的 HelloWorldController 类:
public class HelloWorldController : Controller
{
public ViewResult Index()
{
return View((string)null);
}
[HttpPost]
public ViewResult Index(String name)
{
return View(name);
}
}
一个相应的视图 Index.aspx 位于 Views/HelloWorld 文件夹中。最初的框架使用了 ASPX 视图引擎,这使得混合 C # 代码和 HTML 不像当前的 Razor 代码那么好:
<%
常见的布局和 HTML 结构是通过母版页实现的,视图在其@Page 指令中指定母版页。在此示例中,将有一个共享母版页 Site。在视图/共享文件夹中的 Master.aspx:
<%
框架不需要被告知控制器或视图的位置。它内置了约定的思想,用于路由和控制器/视图位置。
提供了默认的路由/controller/action,框架将自动在 Controllers 文件夹中查找与 URL 名称匹配的控制器类。然后,它将查找名称与 URL 中的名称相匹配的控制器的方法。类似地,框架将在视图文件夹中查找具有正确名称的视图。开发人员还可以自由地用自己的约定替换这些约定,自定义路由或连接自己的控制器工厂和/或视图引擎。
总的来说,像这样的 Hello World 示例,甚至简单的类CRUD 功能看起来比 Web Forms更复杂,更难实现。这就是为什么
3、ASP.NET MVC or Web Forms?
MVC仍在继续发展,它的2.0版本于2010年3月发布,比.Net Framework 4.0发布早了一个月。ASP.NET 4.0进一步改进了Web Forms,除了其他新特性之外,现在可以禁用视图状态(View State),除非在那些你显式启用的控件上,而且还可以对Web Forms页面使用路由模块。
微软面临着严峻的挑战。它在 Web Forms 方面有着巨大的投资和用户基础,同时,它必须转向 MVC作为未来的战略。自
不管微软如何定位这两个框架,ASP.NET 开发者社区的反应是好坏参半的。一些人在它宣布之后就对它充满热情,并认为它是 ASP.NET 所需要的改变,类似于
对于许多经常使用 Web Forms 的人来说,最初的反应是怀疑,他们认为 Web Forms 是一个成熟而稳定的框架,可以构建任何具有成本效益的东西,而 MVC 则是纯粹主义者和专家的实验。我们可以
MVC 的问题在于,即使对于“专家”来说,它也会占用大量宝贵的时间,并且需要大量的努力。企业的驱动力是基于“快速解决方案”,而不管其背后的技术是什么。WebForms 是一种节省时间和金钱的 RAD 技术。任何需要更多时间的事情都是企业所不能接受的。
时间/金钱是为什么选择Web Forms而不是 MVC 的最大原因。如果你的团队中的大多数人都知道WebForms,而你又没有时间让他们在 MVC 上加快速度,那么产生的代码可能不是高质量的。学习 MVC 的基础知识,然后去做你需要做的复杂的页面是非常不同的事情。学习曲线很高,所以你需要在你的预算中考虑到这一点。
MVC的复杂性和学习曲线是它的缺点之一。.NET开发人员需要编写更多的代码来实现使用服务器控件和视图状态获得的相同功能。用
“我已经看到了框架的早期构建,但是对于我来说,如何有效地处理更复杂的页面还不是很清楚。我过去已经构建了几个 Web 框架,它们使用了类似于 MVC 的方法,虽然您可以轻松地完成许多简单的事情,但是根据我的经验,当您的页面包含许多不同的、有些独立的组件时,这种方法就会开始分崩离析。通过基于控制器的方法管理这种复杂性(不管理任何状态)要比 Web 窗体现在提供的方法困难得多。
因为你没有使用 WebForms,所以不能使用任何 ASP.NET 控件。这意味着如果你想创建一个 GridView,你将运行一个 for 循环并手动创建table。如果你想在 MVC 中使用 ASP.NET Wizard向导,那么你必须自己创建。你需要记住的是,你是否能从重新创造所有的东西中获益?总的来说,我更喜欢Webforms框架,因为它有丰富的控件套件和自动管道“
另一个产生一些阻力的地方是,在视图中将代码与标记混合在一起,这被视为退回到Web Forms所抛弃的Classic ASP时代。我们可以在
"现在有些人(可能是从未编写过Classic ASP 程序的人)决定是时候回到把代码和内容混在一起并称之为“关注点分离”的时代了。"
"MVC 最大的缺点是我们回到了 ASP 的时代。还记得混合服务器代码和 HTML 的意大利面条代码吗? ? ?哦,我的上帝,尝试阅读一个 混合了Javascript,HTML,JQuery,CSS,服务器标签等大杂烩的MVC aspx 页面。"
还有人担心放弃对Web Forms的现有投资,比如知识、服务器控件、工具和基础设施,转而支持一个全新的框架。对于那些在Web Forms上投入了大量资金的公司来说,这不是一个容易的决定。
对我来说,这些最初的反应,特别是他们之间关于MV的复杂性C和没有Web Forms抽象Web的共识,证明了微软必须向MVC迈进。这个问题包含了一个完美的例子:
“这怎么可能? 没有视图? 没有事件?”
这些都是开发者社区即将落后于Web的症状,正是在这个时候,对 HTML、 HTTP 和 JavaScript 的良好理解将成为任何网络开发者的重要技能!
让我告诉你,我也是其中之一。
大约在这个时候,我已经在微软的技术领域工作了5年。我使用 VB6和 Win Forms、基于 WCF SOAP 的服务和 ASP.NET 中偶尔出现的内部站点进行桌面开发。
我清楚地记得在尝试构建一个示例站点时浏览了 MVC2文档,并对其复杂性感到恼火。我很难理解Web是无状态的,并且在浏览器和服务器之间管理状态非常困难!我的直觉告诉我,当某些UX事件触发时,你应该能够运行代码来响应它,这些代码能够访问当前状态。这在Win Forms中工作得很好,在Web Forms中也得到了模拟,但与MVC发生了正面冲突,MVC毫无顾忌地暴露了Web的HTML、HTTP和JavaScript现实。
与此同时,我讨厌我在工作中看到的少数Web Forms应用程序(我们设法将它们转换成一堆无法遵循的意大利面条式代码背后的混乱),并且知道一定有更好的方法。即使在我转换到MVC之后,在多年的Windows开发之后,我仍然花了几年的时间来适应严酷的现实和Web的局限性!
在微软之外,
最初,客户端代码由一组或多或少优雅地绑定在一起的 jQuery 事件处理程序组成。但是随着逻辑向客户机的转移继续,客户端 JavaScript 框架出现了,并试图提供一些结构。到2010年,我们已经有3个主要的框架在争夺我们的注意力:
拥有一个与这些客户端框架相匹配的服务器端框架,对 HTML、 CSS 和 JavaScript 给予完全的控制,以及对 AJAX 请求的一流支持,对于 ASP.NET 保持相关性是必要的。
看来 MVC 来得正是时候!
4、ASP.NET MVC正当时
随着MVC继续向前发展,ASP.NET开发人员的怀疑变成了困惑。用于处理HTML和HTTP的Ruby或PHP开发人员更容易掌握该框架,但传统Web Forms开发人员对其明显的复杂性和与Web Forms相比缺乏功能感到困惑。一旦这个框架在许多人眼中失去了“实验性”的标签,论坛、博客和杂志就会开始讨论何时以及如何采用MVC的正确方法。
MVC 的开发周期继续独立于.NET 框架,在2011年初发布了
为.NET 发布和使用开源库从来没有这么容易过!
当然,在早期使用开源库是可能的,但大多数公司要么依赖于他们内部的库,要么依赖于微软的库,像Telerik这样的Web Forms控件是一个常见的例外。
NuGet 改变了这种情况!
此外,NuGet 完美匹配了MVC 的可插拔特性。
关于哪个
# This was the future!
Install-Package MiniProfiler
正是在这个时候,随着 MVC 3作为最新的版本发布,许多开发人员和公司开始意识到 MVC 将继续发展。慢慢地,公司以低风险项目或概念验证悄悄地进入 MVC,开发人员也逐渐习惯了。随着公司和开发人员都获得了使用 MVC 的经验,MVC 开始成为新开发的默认选择。
更重要的是,MVC 成功地实现了关注点分离和 TDD。
但那不是全部。微软发布了
与此同时,客户端 JavaScript 框架的日益普及和移动应用程序的出现增加了对 HTTP 服务的需求,REST (
因此,当2012年中发布
public class ProductsController: ApiController
{
public IEnumerable<Product> GetAllProducts()
{
return repository.GetAll();
}
public Product GetProduct(int id)
{
Product item = repository.Get(id);
if (item == null) throw new HttpResponseException(HttpStatusCode.NotFound);
return item;
}
public Product PostProduct(Product item) { ... }
public void PutProduct(int id, Product product) { ... }
public void DeleteProduct(int id) { ... }
}
不久之后,
那时,ASP.NET 团队已经习惯于频繁发布引入更新和新库的版本。在2012年,他们进一步改进了 ASP.NET,将 SignalR 库作为 NuGet 包发布。这为开发人员提供了一个工具,使他们能够轻松地在 ASP.NET 应用程序中实现实时功能。
有了 SignalR,扩展的 ASP.NET 家族就完整了。
5、One ASP.NET
在2013年底发布了.NET框架的4.5.1版本。在
所有框架重新命名为 One ASP.NET
Web API在这次发布中发布了2.0版本。在其他特性中,对 OData (开放数据协议)的支持得到了改进,增加了一个实现 CORS (跨来源资源共享)的特定包,最重要的是,引入了现在无处不在的属性路由:
[Route("api/books")]
public IEnumerable<Book> GetBooks() { ... }
同时,
用Bootstrap 3更新了默认的项目模板,这是一个很好的理由来看看MVC主页的演变:
MVC 主页从 MVC 3(顶部)到 MVC 5(底部)的演变
甚至 Web 窗体也继续接收新特性。有趣的是,这些特性中的大部分都是为了让 Web Forms 更接近 MVC。开发人员现在可以使用模型绑定器、数据注释、路由或 Unobtrusive JavaScript,这些功能最初是作为 MVC 特性而存在的。
6、结论
ASP.NET以良好的状态到达2014年,在One ASP.NET下提供了几个库,以适应不同的Web应用程序的需求。您可能不是唯一一个认为该框架已经达到其全部潜力并将在几年内保持稳定的人。
在 ASP.NET 之外,
正如我们将在下一篇文章(第3部分)中看到的,ASP.NET 团队对于 ASP.NET 的计划要比增量改进大得多。他们可以看到开放源码和多平台开发的潜力,并且对开放源码社区可以给其框架带来的好处并不陌生。
Part III
0、摘要
在ASP.NET进化系列的第三部分也是最后一部分。我们将看到ASP.NET过渡到ASP.NET Core
-
开源的,跨平台的
-
完全包含了Web的本质
编辑注意: 本教程的 vNext 和展望未来部分正在更新,以反映最新的变化。
在这个系列的最后一篇文章中,我们将看到它演变的最后一步——一个完成了从一个试图隐藏和抽象网络的封闭平台到一个完全拥抱网络本质的开源跨平台的转变。
1、ASP.NET Core 出场(2014-至今)
看起来 ASP.NET 团队终于通过 One ASP.NET 的想法和不同的框架实现了他们的长期愿景。但这远非事实。团队正忙于更深入地研究框架,甚至研究它的.NET 的基本本质。他们甚至决定在内部代号为 ASP.NET vNext,而不是它(当时)的公共名称 ASP.NET 5。
这让很多人大吃一惊,但其根源可以在项目
Project Katana 于2013年发布,现有的两个 ASP.NET 库 Web API 和 SignalR 与其兼容。例如,由于 OWIN 兼容性,
到今天为止,OWIN 已经被 ASP.NET Core所取代,因为它实现了相同甚至更多的目标。
回顾过去,很容易看到 ASP.NET 团队在开始 ASP.NET Core之旅之前测试方向并获得知识
2、ASP.NET vNext早期开发阶段
早在2014年5月,大卫•福勒(David Fowler)就宣布 vNext 正在筹备中:
“在过去的几个月里,我一直致力于我们现在所称的 ASP.NET vNext 。我们研究了当今我们的生态系统中存在的一些常见问题,并采用了在.NET、ASP.NET和Web开发中学习到的最佳实践。结合他们提出了以下要求。”
在他的博客文章的最后,人们可以读到以下内容:
“奖励: 我们正在与 Mono 团队合作,使其与 linux,osx 一起工作”
尽管 Mono 已经存在了相当长的一段时间(2004年发布的1.0版本) ,但这是微软第一次构建跨平台的.NET产品!在后续的博客文章中,他分享了新体系结构的初步细节,包括新的运行时间(在当时被称为 KRuntime)、新的 HTTP 抽象、简化宿主以及统一 MVC/Web API 的计划。
大约在同一时间,Scott Hanselman 也在他的
{
"webroot": "wwwroot",
"version": "1.0.0-*",
"exclude": [
"wwwroot"
],
"packExclude": [
"**.kproj",
"**.user",
"**.vspscc"
],
"dependencies": {
"Microsoft.AspNet.Mvc ": "1.0.0-beta1",
"Microsoft.AspNet.Hosting ": "1.0.0-beta1",
"Microsoft.AspNet.Diagnostics": "1.0.0-beta1"
},
"frameworks": {
"aspnet50": { },
"aspnetcore50": { }
},
"commands":{
"web": "Microsoft.AspNet.Hosting --server Kestrel --server.urls http://localhost:50
}
}
虽然在 Core 1.1.1中遗憾地放弃了对 project.json 的更改,取而代之的是简化的.csproj (为了保持与现有工具的兼容性) ,它是团队采用的大胆方法的另一个很好的例子。
Scott Hanselman 也给出了驱动团队的开源思维的一个重要提示:
"ASP.NET 和 Web 工具团队正在进行一些非常酷的工作。这个团队已经在微软推动开放的东西好几年了,我们已经与.NET Core团队和其他团队的创新者联合起来!"
这是一场非常缓慢的革命,他们花了几年时间才完成。还记得我们回头看微软的 AJAX 和它的 MS-PL 许可证吗?很高兴看到,从那些不起眼的开始,团队成功地完全采用了开源。有了 vNext,他们计划用一个新的 CLR 对 ASP.NET 进行彻底的重写,同时在开放的环境下进行开发,使用 GitHub 进行代码和问题跟踪、社区站点,最终在 Apache 许可下发布。
我推荐阅读 Scott Hunter 的精彩文章,
随着 vNext 工作的继续,团队热衷于分享信息和收到反馈。例如,Daniel Roth 在2014年10月为
"作为微软的一部分发布的 ASP.NET .NET Framework 1.0,与 Visual Studio 2002一起于2002年发布。它是Active Server Pages(ASP)的进化,带来了面向对象的设计、.NET基类库(BCLs)、更好的性能以及更多。ASP.NET的设计是为了方便习惯于编写桌面应用程序的开发人员使用ASP.NET Web Forms来构建Web应用程序。随着Web的发展,新的框架被添加到ASP.NET: 2008年是MVC, 2010年是Web Pages, 2012年是Web API和SignalR。这些新框架都建立在ASP.ET 1.0之上。"
在 ASP.NET 5中,ASP.NET 被重新构想,就像2002年 ASP.NET 被重新构想一样。
经过多年对 Visual Studio 中基于 GUI 的工具的关注之后,看到命令行工具作为新框架的一部分出现在新版本中让人耳目一新。最初的预览使用了所谓的 KRuntime,有3种不同的 CLI 工具:
-
Kvm-用于在运行时版本之间安装和切换
-
Kpm-用于恢复项目依赖关系,并将项目打包(或构建)成一个自包含的映像
-
K -用于运行project.json中定义的命令,启动应用程序
一个是 kvm 列出现有版本的运行时,kpm 恢复 & kpm 打包您的项目,最后 k web 在本地主机上运行它。如果这些命令对您来说听起来很陌生,那是因为它们经历了几次重命名。KRuntime 变成 DNX 运行时,命令变成 dnvm、 dnu 和 DNX,而不是 kvm、 kpm 和 k。作为统一的 dotnet CLI 的一部分,ASP.NET Core 1.0将再次改变它们,成为诸如 dotnet list、 dotnet restore、 dotnet publish、 dotnet run 等子命令。
3、ASP.NET vNext vs Node.js
看到 vNext 与 Node.js 如此相似是件有趣的事情,这并非巧合,因为 Node.js 确实受到了 vNext 的影响,与 Ruby、 Go从 Project Katana 和其他项目中学到的东西一起:
ASP.NET vNext vs Node.js
开发过程将继续进行,在2015年11月发布第一个RC(发布候选版本)之前,将发布多达8个beta公开版本。2016年5月当 ASP.NET 5被正式重命名为 ASP.NET Core (ASP.NET vNext 一直是一个内部名称)时,还会有第二个 RC 版本。在RC2发布之前,Scott Hanselman已经宣布了重命名并解释了它的原因(因为它给早期的RC1采用者带来了一些痛苦):
“为什么是1.0?因为整个.NET Core概念是全新的。.NET Core 1.0 CLI 是非常新的。不仅如此.NET Core并不像完整的.NET Framework 4.6.我们仍在探索服务器端图形库。我们仍在探索 ASP.NET 4.6和 ASP.NET Core 1.0之间的差距。”
有了一个能更好地传达ASP.NET和ASP.NET Core之间的区别,团队已经准备好进行最初的发布。
4、ASP.NET Core 到来
.NET Core 1.0最终于2016年6月底发布。它花了两年多的时间开发,但结果是充满希望的。正如微软在其声明中所说:
“我们挑战一切,而不是交付增量更新,这样你就可以拥有一个极其模块化,快速和轻量级的平台,非常适合软件开发的新时代,在这个时代,单一应用程序被可以单独部署的小型、自主的服务所取代。所有这些都是为了保持和扩展.NET最擅长的:开发人员的生产力,以及现代语言和库。最终的结果是一个ASP.NET,你会觉得非常熟悉,而且现在更适合现代web开发。”
在 ASP.NET Core 中创建 Web 应用程序感觉非常类似于创建 MVC/Web API 应用程序。控制器与早期的模型没有太大的不同,事实上这很可能是 ASP.NET MVC 代码:
public class HelloWorldController: Controller
{
public IActionResult Index()
{
return View();
}
[HttpPost]
public IActionResult Index(String name)
{
return View(name);
}
}
相应的使用 Razor 的 Index.cshtml 视图看起来也很熟悉,尽管它暗示了视图中的一个主要变化,
@model String
@if (Model != null) {
<p>Hello @Model</p>
}
<form asp-action="Index">
<p>
<label for="name">Name:</label>
<input id="name" name="name" type="text">
</p>
<input type="submit" value="Say Hi" />
</form>
然而,一旦人们开始触及表面,差异就开始变得明显。
第一个是基于中间件函数的新
ASP.NET Core中的统一请求管道
抛开中间件的概念,我们还内置了一个依赖注入框架,在整个框架中应用依赖倒置模式。还有一个完全不同的项目启动和设置,它反映了新的轻量级托管方法和基于中间件的管道。
一些最直接明显的改进是对Razor的添加,以构建更清晰的视图。我指的是替换旧MVC HtmlHelpers和Partial Views的
当我们拿到1.0版本时,ASP.NET团队正忙于以下版本的开发。2016年11月,1.1.0版本发布了一些改进和细化,比如使用中间件作为过滤器,或者使用标签助手Tag Helper呈现任何视图组件。后者将使视图组件的使用非常类似于任何JavaScript SPA框架中组件的使用。也就是说,要呈现一个名为LatestArticles的视图组件,现在可以简单地编写
<vc:latest-articles></vc:latest-articles>
而不是
@await Component. invokeasync (" LatestArticles ")
在下一个主要版本公开发布之前,还有两个较小的版本,1.1.1和1.1.2。
5、ASP.NET Core 2.0 和未来的路线图
经过
其最大的特性之一是包含了 Razor Pages,这在某种程度上使我们回到了我们在2003年设计Web Forms时讨论的Page Controller(页面控制器)模式!
但是,这次没有表单抽象,而是完全控制了 HTTP 请求和生成的 HTML。我们的 HelloWorld 示例可以实现为一个新的 HelloWorldd.cshtml 页面:
@page
@model HelloWorldModel
@if (Name != null) {
<p>Hello @Name</p>
}
<form method="post">
<p>
<label asp-for="Name "></label>
<input class="form-control" asp-for="Name" />
</p>
<input type="submit" value="Say Hi" />
</form>
与它的代码隐藏文件一起(是的,我们回到了代码隐藏。这不是很有趣吗?)实现页面模型:
public class HelloWorldModel: PageModel
{
[BindProperty]
public String Name { get; set; }
public IActionResult OnPost()
{
Return Page();
}
}
这为框架增加了使用 MVVM (Model View View-Model模型视图-模型)模式的可能性,开发人员可以根据自己的需要混合使用传统的 MVC 方法。
.NET Core 2.0中另一个重要的补充是 IHostingService 的引入。这为您的Web应用程序提供了一种非常方便和直接的方式来运行后台进程。这对于不需要复杂的分布式体系结构的场景非常有用。您可以在
2018年5月发布了2.1.0版本,在众多特性和改进中,它最终将重写的 SignalR 框架引入到了 ASP.NET Core 中。这是 SignalR 的一个更简单、更高性能和更轻量级的版本,旨在扩展和利用.NET Core。
更广泛的.NET Core接受
通过 SignalR 和 Razor Pages,One ASP.NET 下的原始库集最终被移植到.NET Core!(假设 Razor Pages 作为 Web Forms和 Web Pages的对应物)
展望未来,我们可以在即将发布的.NET Core 3.0中看到两个令人兴奋的特性:
-
最终将添加对
-
(过时的部分)不再是试验性的Blazor框架(现在是预览版)将部分随.NET Core 3.0发布。这可以通过以下事实来解释:Blazor的服务器端模型将被提取并重命名为Server- side Blazor(以前称为Razor Components)。基于Web assembly的客户端模型,可以在浏览器中运行.NET,将成为Blazor的唯一模型,并将保持实验版本,尚未准备好投入生产。检查我们的文章关于
让我们不要忘记.NET Core中所做的所有性能改进,以及像Span<T>这样的结构的引入。根据TechEmpower基准测试,NET Core 2.2是第三快的Web服务器(纯文本响应)。该团队承诺在下一个版本中会有更好的性能。
看起来 ASP.NET 的未来是光明的,即使在它第一次发布20年之后!
有趣的是,Razor组件是ASP.NET Core 3.0的一部分,我们又回到了一个封装模板和逻辑的页面模型,能够对UX事件做出反应。尽管这一次它实际上是在相同的进程中运行,除了浏览器中的一个小客户机之外,呈现通过SignalR连接推送的DOM更新。
6、结论
20年是很长的一段时间。在这些年里,我们看到 ASP.NET 在最初发布之后崛起,与Web的变化步伐作斗争、纠正它的过程,最终将自己重塑为运行在 Linux 上最快的服务器之一。
一路走来,由于 ASP.NET 团队的努力,一个带有“非本地发明”综合症的生态系统的封闭源代码微软产品在很大程度上已经变成了一个开源社区。
我希望你能喜欢这次怀旧之旅,我只想知道未来会带来什么!