开发者 | Microsoft |
---|---|
当前版本 | 5.2.3(2015年2月9日[1]) |
预览版本 | 6.0.0-rc1(2015年11月18日[2]) |
编程语言 | .NET 编程语言,例如C#、VB.NET |
类型 | ASP.NET、MVC |
许可协议 | Apache License 2.0 |
网站 | www |
ASP.NET MVC 是微软发展的 Web 应用程序开发框架之一,以ASP.NET为核心发展,属于 One ASP.NET 技术架构的成员之一。
虽然与 Web Forms 开发模型相同的核心,但它是以 MVC (Model/View/Controller) 的设计模式概念为基础,将 Model、View 与 Controller 三者分开设计,其核心理念之一为关注点分离 (Separation of Concerns)。由于使用的是完全不同的设计概念,因此 Web Form 和 MVC 应用程序得以共存,也可以择一使用。ASP.NET MVC 的主程式被封装于 System.Web.Mvc.dll 内。
ASP.NET MVC 早期以 MS-PL (Microsoft Public License) 授权规范 [3] 开放源代码,自2012年3月起改为 Apache License 2.0 规范,后续的版本仍持续以 Open Source 方式释出源代码。
ASP.NET MVC 也是下一代 .NET 平台 .NET Core 的钦定 Web 应用程序开发框架。
程式设计模型
ASP.NET MVC 采用的 MVC 遵循 Model/View/Controller 分离的架构,依照关注点分离的概念,以及习惯取代配置 (Convention over Configuration) 的理念,ASP.NET MVC 将三个不同的部件分离到三个不同的资料夹内,Model 配置于 Models 资料夹、Controller 配置于 Controllers 资料夹、View 则配置于 Views 资料夹等,在 Visual Studio 内的 ASP.NET MVC 专案范本也确实的依这个原则产生,但这也是很容易被外界误解的地方,以为一定要照规则走才能正常作业,然而事实上 Model 和 View 和 Controller 不但可以分开配置,甚至还可以切割成不同专案。
ASP.NET MVC 的生命周期 [4] 源自 HTTP 的要求 (Request),当 ASP.NET MVC 设置于 IIS 上的 ASP.NET Routing Module (位于 System.Web.Routing.dll 内的 UrlRoutingModule 类别) 拦截到 HTTP 的要求时,会解析 HTTP 的 URL,取得与路由表 (Routing Table) 对应的 URL 参数,找出 Controller 的位置,并使用 Controller Activator 初始化 Controller 物件,并将 HTTP 的要求资讯转送到 Controller 内;Controller 内在处理完成之后,会回传一个继承自 ActionResult 的结果物件,ActionResult 本身会将所需要的讯息与结果输出到 HTTP 回应资料流,并回传到使用者的浏览器 (或 HTTP 用户端),完成一整个的 HTTP 动作。
模型 (Model)
在 ASP.NET MVC,资料模型并不是强制必要的项目,依照习惯取代配置原则,ASP.NET MVC 会认为资料的模型会放在 Models 资料夹内,但这并不是强制要求,所以资料模型可以放在任何专案,只要 Controller 能够找到并存取即可。在 MVC 应用程序的 Model 多半会使用强型别的 DTO 或 POCO 来组合运用,因此大多数的 ASP.NET MVC 范例会使用 ADO.NET Entity Framework 作为例子,但这并不代表 ASP.NET MVC 一定得用 Entity Framework 或是 ORM-based 的解决方案 (如 NHibernate),若是需要或是维持相容性,MVC 还是能使用传统的 ADO.NET DataTable 或 DataSet,然而依现代应用程序的架构,使用 DTO/POCO 等强型别的资料方案会较适合。
虽然 Model 在 ASP.NET MVC 内是被动的角色,但 ASP.NET MVC 还是提供了一些支援来简化处理与传递 Model 的作业,例如 Model Binding 技术,能将传入 Controller 的资料简化为使用 Model 参数即可;Model Validation 则是可以在 Controller 内对 Model 的检验进行处理,可使用程式码或是用特征项 (Attribute) 的方式来处理。
模型验证 (Model Validation)
模型验证功能 [5] 是由 .NET Framework 3.5 SP1 开始新增的 System.ComponentModel.DataAnnotations
命名空间所提供的资料标记为基础所实作的功能,开发人员可透过加入简单的资料验证特征,就可以在 Controller
中使用 ModelState.IsValid
来确认模型是否有效 (即符合资料标记的要求)。
例如下列程式码,每个属性都套用了资料标记的特征。
public class Movie
{
public int ID { get; set; }
[StringLength(60, MinimumLength = 3)]
public string Title { get; set; }
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")]
[Required]
[StringLength(30)]
public string Genre { get; set; }
[Range(1, 100)]
[DataType(DataType.Currency)]
public decimal Price { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")]
[StringLength(5)]
public string Rating { get; set; }
}
控制器 (Controller)
ASP.NET MVC 的 Controller
物件负责处理 HTTP 的要求,并将结果以 ActionResult
的物件回传 (不过这也不是强制的,若 MVC 核心发现方法是 void
时,预设会回传 EmptyResult
[6]),再由 MVC 核心接手呼叫 ActionResult
内的实作来取得 HTTP 回传的内容。所有应用程序内的 Controller
物件都要继承自 Controller
基础类别,以获取 Controller
所需的功能。
方法
开发人员依照需要于 Controller
内配置一个或多个方法以处理 HTTP 讯息,依预设,Controller
内的 public
方法都可以由 HTTP URL 的路由转入 (在不改变预设路由的情况下),若是不想对外公开 (内部用的方法) 时,可以在方法上加上 [NonAction]
特征项,以封锁方法不被路由取得。每个方法预设会由 HTTP GET 取用,若是需要由其他的 HTTP 动词唤起,可在方法上加入 [HttpPost]
/[HttpPut]
/[HttpDelete]
或是 [ActionVerb]
来设定允许由哪个 HTTP 动词唤起。
方法的参数
Controller
内的方法可以使用参数,参数的来源有两种:
- 由 URL 提供,这个功能由 ASP.NET Routing 实作,只要应用程序的路由表有注册 URL 的参数 (可以是 URL 路径内的片段,也可以是 Query String)。
- 由 HTTP 的讯息提供,当
Controller
的方法宣告了[HttpPost]
[HttpPut]
特征项时,Controller
的 Model Binding 会将讯息的相对栏位系结到 Model 内。
基本上 Controller
内方法的参数应使用允许 NULL
的资料型态,若是数值型别则应使用 Nullable<T>
型别的参数,string
因为本来就可以接受 NULL
所以无需使用 Nullable<T>
,否则当 Model Binding 找不到指定参数的资料时,会掷回例外。若不使用参数接值,ASP.NET MVC 也提供了 Controller.Request
属性来取得 HTTP 的要求,这表示开发人员可以自行操作 Request.QueryString
与 Request.Form
取得 HTTP 的讯息资料。
方法回传值
Controller 内的方法一般都需要回传 ActionResult
或其衍生类别的物件,ASP.NET MVC 提供了下列内建的 ActionResult
实作品供开发人员选择。
ViewResult
物件,这个物件内装载了IView
界面的资讯,以及IViewEngine
的资讯,实际产生输出资料的会是 IViewEngine,以及其指示的 View 物件。PartialViewResult
物件,与ViewResult
相似,但它回传的是"部分展示",即使用者控件的View。ContentResult
物件,装载由使用者自订的 Content-Type 以及资料。EmptyResult
物件,表示不回传任何东西。HttpUnauthorizedReuslt
物件,表示动作没有被授权(即 HTTP 401)的错误讯息。JavaScriptResult
物件,表示回传的是JavaScript指令码。JsonResult
物件,表示回传的是JSON资料。FileResult
物件,表示回传的是一个档案资料。RedirectResult
物件,表示回传的是一个重导向 (HTTP Redirect) 指令。RedirectToRouteResult
物件,与RedirectResult
类似,但是它是重导向给一个 Route 的路径。RedirectToActionResult
物件,与RedirectResult
类似,但是它是重导向到指定的 Controller 的动作。
若需要自行设计自己的 ActionResult
,可继承 ActionResult
类别并覆写其 ExecuteResult()
方法,以产生自订的 HTTP 回应内容 [7]。
在 ASP.NET MVC 6 中,ActionResult
类别由 IActionResult
界面取代,以提供更强的界面合约机制 [8]。
动作过滤器
动作过滤器 (Action Filter) [9]是 ASP.NET MVC 提供扩充 HTTP 处理流程能力的机制。ASP.NET MVC 提供了预设的几种 Action Filter 给开发人员使用:
AuthorizeAttribute
: 控制授权的动作。HandleErrorAttribute
: 控制处理错误的动作。OutputCacheAttribute
: 控制执行动作的结果输出快取的动作。RequireHttpsAttribute
: 控制是否强制使用 HTTPS (SSL) 的动作。
若是需要,开发人员利用实作 ActionFilterAttribute
类别来实作自订的动作过滤器,ActionFilterAttribute
提供数种方法可覆写:
OnAuthorization
: 当动作需要授权时触发。OnException
: 当动作发生例外时触发。OnActionExecuting
: 在动作执行前呼叫。OnActionExecuted
: 在动作执行后,Controller 回传ActionResult
前呼叫。OnResultExecuting
: 在 Controller 回传ActionResult
后,但在产生结果之前呼叫。OnResultExecuted
: 在产生结果后呼叫。
其中 OnActionExecuting
和 OnResultExecuting
所提供的事件参数包含了 Cancel
属性,开发人员可决定是否要取消动作;OnActionExecuted
和 OnResultExecuted
的事件参数则包含了 Exception
属性与 ExceptionHandled
属性,Exception
属性内含执行动作与产生结果时产生的 Exception (没有的话为 NULL
),若是动作过滤器内可处理掉 Exception,则可设定 ExceptionHandled = true
,这样就不会中断动作的执行。
检视 (View)
在 ASP.NET MVC 中,检视功能通常是指由 View Engine (检视引擎) 所产生的 HTML 内容。
ASP.NET MVC 在早期 (v1.0-2.0) 时使用的是 ASPX-based View Engine,其副档名与 ASP.NET Web Form 相同,并且支援 .aspx (检视)、.ascx (部分检视) 以及 .master (主版页面) 三种,其标记语法也相容于 ASP.NET Web Form 的 <% ... %> 语法,也因为采用了 Web Form 的语法 (和以前的 ASP 语法很相像),导致 ASP.NET MVC 初期容易被误解为 ASP 复辟。
下列指令为 ASPX-based View Engine 的例子:
<ul>
<%foreach (var item in Products)
{ %>
<% if (item.IsInStock)
{ %>
<p><%=item.ProductName%> is in stock</p>
<% }
else
{ %>
<p><%=item.ProductName%> is not in stock</p>
<% } %>
<%} %>
</ul>
在 ASP.NET MVC v3.0 开始,ASP.NET MVC 团队提出了新的 View Engine,称为 Razor-based View Engine [10],其检视内使用的程式指令为 Razor,是微软特别为 ASP.NET MVC 而开发,其副档名为 .cshtml (C#) 或是 .vbhtml (VB),但 URL 内不必包含 .cshtml 或 .vbhtml,表示不需要副档名,其程式码内使用的语法也更简洁。
下列指令为 Razor-based View Engine 的例子:
<ul>
@foreach (var item in Products)
{
@if(item.IsinStock)
{
@item.ProductName is in stock
} else {
@item.ProductName is in stock
}
}
</ul>
但不论是 ASPX 或是 Razor,ASP.NET MVC 的检视让开发人员能使用指令弹性的在 HTML 内自由添加资料或是其他的 HTML 内容,让 MVC 检视可调整的自由度更大。
检视功能虽然是 MVC 的其中一环,但在 ASP.NET MVC 中不一定是必要项 (若方法回传的不是 ViewResult 物件时就不会驱动 View Engine 的功能),应用程序可以不回传以 HTML 为主的内容,此时回传的资料会取决于 ActionResult 的 ExecuteResult() 的输出内容。
HTML Helpers
为辅助检视产生特定的 HTML,例如针对 Routing 路由表的超链接、表单的 HTML 或是其他需要的 HTML 内容,ASP.NET MVC 设计了一组 HTML Helper [11],以 Html. 为开头,并同时提供针对弱型别 Model 与强型别 Model 的实作 (方法中有 For 字样的),例如:
<h2><%= Html.Encode(ViewData["Message"]) %></h2>
<br /><br />
<% using(Html.BeginForm("HandleForm", "Home")) %>
<% { %>
Enter your name: <%= Html.TextBox("name") %>
<br /><br />
Select your favorite color:<br />
<%= Html.RadioButton("favColor", "Blue", true) %> Blue <br />
<%= Html.RadioButton("favColor", "Purple", false)%> Purple <br />
<%= Html.RadioButton("favColor", "Red", false)%> Red <br />
<%= Html.RadioButton("favColor", "Orange", false)%> Orange <br />
<%= Html.RadioButton("favColor", "Yellow", false)%> Yellow <br />
<%= Html.RadioButton("favColor", "Brown", false)%> Brown <br />
<%= Html.RadioButton("favColor", "Green", false)%> Green
<br /><br />
<%= Html.CheckBox("bookType") %> I read more fiction than non-fiction.<br />
<br /><br />
My favorite pet: <%= Html.DropDownList("pets") %>
<br /><br />
<input type="submit" value="Submit" />
<% } %>
部分检视
部分检视 (Partial View) [12]允许开发人员产生网页内容的一部分,在 ASPX View Engine 中使用 .ascx 为副档名,而 Razor View Engine 则一样采用 .cshtml/.vbhtml 作为副档名,在 View 程式中呼叫 Html.RenderPartial() 或是 Html.Partial() 即可产生部分检视的内容,如下例:
@Html.Partial("~/Views/Shared/_Product.cshtml", product);
版本历程
日期 | 版本 |
---|---|
2007/12/10 | ASP.NET MVC CTP |
2009/03/13 | ASP.NET MVC 1.0[13] |
2009/12/16 | ASP.NET MVC 2 RC[14] |
2010/02/04 | ASP.NET MVC 2 RC 2[15] |
2010/03/10 | ASP.NET MVC 2[16] |
2010/10/06 | ASP.NET MVC 3 Beta[17] |
2010/11/09 | ASP.NET MVC 3 RC[17] |
2010/12/10 | ASP.NET MVC 3 RC 2[18] |
2011/01/13 | ASP.NET MVC 3[19] |
2011/09/20 | ASP.NET MVC 4 Developer Preview[20] |
2012/02/15 | ASP.NET MVC 4 Beta[21] |
2012/03/31 | ASP.NET MVC 4 RC[22] |
2012/08/15 | ASP.NET MVC 4[23] |
2013/05/30 | ASP.NET MVC 4 4.0.30506.0 [24] |
2013/06/26 | ASP.NET MVC 5 Preview [25] |
2013/08/23 | ASP.NET MVC 5 RC 1[26] |
2013/10/17 | ASP.NET MVC 5[26] |
2014/01/17 | ASP.NET MVC 5.1[26] |
2014/02/10 | ASP.NET MVC 5.1.1[26] |
2014/04/04 | ASP.NET MVC 5.1.2[26] |
2014/06/22 | ASP.NET MVC 5.1.3[26] |
2014/07/01 | ASP.NET MVC 5.2.0[26] |
2014/08/28 | ASP.NET MVC 5.2.2[26] |
2015/02/09 | ASP.NET MVC 5.2.3[26] |
2015/11/07 | ASP.NET MVC 6.0.0-beta1[27] |
2015/11/18 | ASP.NET MVC 6.0.0-rc1[27] |
与 Web Form 模型的比较
ASP.NET MVC 虽然与 Web Forms 是系出同门的 ASP.NET 开发技术,但两者是完全不同的走向,因此也经常被拿来做比较。
基本上,Web Form 和 MVC 所擅长的领域是不同的:
- Web Forms 擅长的是快速开发,以控件为主的事件驱动开发方式,熟悉以事件驱动为基础开发的开发人员能以较短时间快速进入 Web 应用程序的开发领域。
- MVC 擅长的是架构导向的开发,以 HTTP 处理流程为主,若是熟悉 ASP 以及 HTTP 处理流程的开发人员 (例如 PHP, JSP, Perl, node.js, Python 等) 能快速的学会并应用。
下表为 Web Forms 与 MVC 的比较[28]。
ASP.NET Web Forms | ASP.NET MVC |
---|---|
以网页或控件的生命周期为主,采用 Code-Behind 方式撰写程式码,每个网页都是它自己的控制器。 | 以标准的 HTTP 流程 (Request/Response) 为主,以 Controller 来处理要求与回应,程式码写在 Controller 内,由 URL 路由决定使用的控制器。 |
没有关注点分离的概念,网页和程式码是紧密的结合。 | 有关注点分离的概念,Controller 和 View 并没有直接关联,Controller 内的方法可依需求来决定使用的 View。 |
程式码较难依职责切割,因此较难以施行单元测试以及自动测试。 | 可测试性是 MVC 的关键功能,因此能很容易的导入单元测试与自动测试 (或是测试驱动开发) |
为了保存网页状态而导入 ViewState,使得网页容易变得笨重,但提供与 Windows Forms 相似的作法。 | 本身是以无状态方式提供,因此没有 ViewState,但状态保存要由开发人员处理。 |
需经由完整的网页生命周期 (Page Life Cycle)。 | 无网页生命周期,由要求周期 (Request Cycle) 替代。 |
为了要做到与 Windows Forms 类似的作法,Web Forms 提供了相当多的控件,它基本上会自动产生相应的 HTML, CSS, JavaScript,所以只需要最少的相关知识即可。 | 需要有较完整的 HTML, CSS, JavaScript 的知识,否则无法随心所欲的操作 View。 |
对 HTML 没有太多的控制能力,或是要花较多额外的工作处理。 | 具有完整的 HTML 控制能力。 |
能在有限的知识之下实行快速开发。 | 以 HTTP 流程步骤为主,生产力取决于开发人员的能力。 |
适合小型开发团队与小规模的应用程序。 | 适合职责分离的团队,并且适合中大型的应用程序。 |
知名应用
在此列举一些使用 ASP.NET MVC 开发的知名网站:
- StackOverflow.com,采用 ASP.NET MVC 开发的大型分散式应用程序,目前为全球最知名的技术论坛群[29]。
- MSDN Forums
- TechNet Forums
- MSDN Blog Platform
- TechNet Blog Platform
- 华人健康网。
- Codeplex
- docs.com
- GoDaddy
- DELL
- 米格国际(Lativ)
- 活动通 Accupass
- TutorABC
- 点部落,台湾最大的技术部落格社群。
参考
- ^ ASP.NET MVC 5.2.3, Web Pages 3.2.3 and Web API 5.2.3 Release
- ^ Announcing ASP.NET 5 Release Candidate 1
- ^ MS-PL 授权规范
- ^ ASP.NET MVC Lifecycle
- ^ Adding Validation
- ^ Extreme ASP.NET - The Life And Times of an ASP.NET MVC Controller
- ^ How to Create Custom ActionResult Method in ASP.Net MVC4
- ^ Controllers, Actions, and Action Results
- ^ Filtering in ASP.NET MVC
- ^ Introduction to ASP.NET Web Programming Using the Razor Syntax
- ^ 使用 HTML Helper 在 ASP.NET MVC 呈现表单
- ^ Partial View in ASP.NET MVC 4
- ^ Download ASP.NET MVC 1.0 from Official Microsoft Download Center. Microsoft. [17 January 2015].
- ^ Phil Haack. ASP.NET MVC 2 RC Released. [17 January 2015].
- ^ Phil Haack. ASP.NET MVC 2 RC 2 Released. [17 January 2015].
- ^ Download ASP.NET MVC 2 RTM from Official Microsoft Download Center. Microsoft. [17 January 2015].
- ^ 17.0 17.1 ASP.NET MVC 3. The Official Microsoft ASP.NET Site. [17 January 2015].
- ^ ScottGu's Blog - Announcing ASP.NET MVC 3 (Release Candidate 2). [17 January 2015].
- ^ Download ASP.NET MVC 3 RTM from Official Microsoft Download Center. Microsoft. [17 January 2015].
- ^ ASP.NET. CodePlex. [17 January 2015].
- ^ ASP.NET MVC 4. The Official Microsoft ASP.NET Site. [17 January 2015].
- ^ MSDN Blogs. Microsoft. [17 January 2015].
- ^ MSDN Blogs. Microsoft. [17 January 2015].
- ^ ASP.NET and Web Tools 2012.2 Release Notes. The Official Microsoft ASP.NET Site. [17 January 2015].
- ^ Microsoft ASP.NET Team. ASP.NET and Web Tools for Visual Studio 2013 Release Notes. The Official Microsoft ASP.NET Site. [17 January 2015].
- ^ 26.0 26.1 26.2 26.3 26.4 26.5 26.6 26.7 26.8 NuGet Gallery - Microsoft ASP.NET MVC 5.2.2. [17 January 2015].
- ^ 27.0 27.1 aspnet/Mvc. GitHub. [2015-10-16].
- ^ Difference betweeen ASP.NET WebForms and ASP.NET MVC
- ^ Stack Overflow: The Architecture - 2016 Edition