使用者:小朱/沙盒/ASP.NET MVC

ASP.NET MVC
開發者Microsoft
當前版本5.2.3(2015年2月9日 (2015-02-09) [1]
預覽版本6.0.0-rc1(2015年11月18日 (2015-11-18) [2]
編程語言.NET 程式語言,例如C#VB.NET
類型ASP.NETMVC
許可協議Apache License 2.0
網站www.asp.net/mvc/

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 多半會使用強型別的 DTOPOCO 來組合運用,因此大多數的 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 內的方法可以使用參數,參數的來源有兩種:

  1. 由 URL 提供,這個功能由 ASP.NET Routing 實作,只要應用程式的路由表有註冊 URL 的參數 (可以是 URL 路徑內的片段,也可以是 Query String)。
  2. 由 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.QueryStringRequest.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 給開發人員使用:

  1. AuthorizeAttribute: 控制授權的動作。
  2. HandleErrorAttribute: 控制處理錯誤的動作。
  3. OutputCacheAttribute: 控制執行動作的結果輸出快取的動作。
  4. RequireHttpsAttribute: 控制是否強制使用 HTTPS (SSL) 的動作。

若是需要,開發人員利用實作 ActionFilterAttribute 類別來實作自訂的動作過濾器,ActionFilterAttribute 提供數種方法可覆寫:

  • OnAuthorization: 當動作需要授權時觸發。
  • OnException: 當動作發生例外時觸發。
  • OnActionExecuting: 在動作執行前呼叫。
  • OnActionExecuted: 在動作執行後,Controller 回傳 ActionResult 前呼叫。
  • OnResultExecuting: 在 Controller 回傳 ActionResult 後,但在產生結果之前呼叫。
  • OnResultExecuted: 在產生結果後呼叫。

其中 OnActionExecutingOnResultExecuting 所提供的事件參數包含了 Cancel 屬性,開發人員可決定是否要取消動作;OnActionExecutedOnResultExecuted 的事件參數則包含了 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 開發的知名網站:

參考

  1. ^ ASP.NET MVC 5.2.3, Web Pages 3.2.3 and Web API 5.2.3 Release
  2. ^ Announcing ASP.NET 5 Release Candidate 1
  3. ^ MS-PL 授權規範
  4. ^ ASP.NET MVC Lifecycle
  5. ^ Adding Validation
  6. ^ Extreme ASP.NET - The Life And Times of an ASP.NET MVC Controller
  7. ^ How to Create Custom ActionResult Method in ASP.Net MVC4
  8. ^ Controllers, Actions, and Action Results
  9. ^ Filtering in ASP.NET MVC
  10. ^ Introduction to ASP.NET Web Programming Using the Razor Syntax
  11. ^ 使用 HTML Helper 在 ASP.NET MVC 呈現表單
  12. ^ Partial View in ASP.NET MVC 4
  13. ^ Download ASP.NET MVC 1.0 from Official Microsoft Download Center. Microsoft. [17 January 2015]. 
  14. ^ Phil Haack. ASP.NET MVC 2 RC Released. [17 January 2015]. 
  15. ^ Phil Haack. ASP.NET MVC 2 RC 2 Released. [17 January 2015]. 
  16. ^ Download ASP.NET MVC 2 RTM from Official Microsoft Download Center. Microsoft. [17 January 2015]. 
  17. ^ 17.0 17.1 ASP.NET MVC 3. The Official Microsoft ASP.NET Site. [17 January 2015]. 
  18. ^ ScottGu's Blog - Announcing ASP.NET MVC 3 (Release Candidate 2). [17 January 2015]. 
  19. ^ Download ASP.NET MVC 3 RTM from Official Microsoft Download Center. Microsoft. [17 January 2015]. 
  20. ^ ASP.NET. CodePlex. [17 January 2015]. 
  21. ^ ASP.NET MVC 4. The Official Microsoft ASP.NET Site. [17 January 2015]. 
  22. ^ MSDN Blogs. Microsoft. [17 January 2015]. 
  23. ^ MSDN Blogs. Microsoft. [17 January 2015]. 
  24. ^ ASP.NET and Web Tools 2012.2 Release Notes. The Official Microsoft ASP.NET Site. [17 January 2015]. 
  25. ^ 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. ^ 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. ^ 27.0 27.1 aspnet/Mvc. GitHub. [2015-10-16]. 
  28. ^ Difference betweeen ASP.NET WebForms and ASP.NET MVC
  29. ^ Stack Overflow: The Architecture - 2016 Edition