開發者 | 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