ASP.NET MVC Framework

ASP.NET MVC Framework是微軟在ASP.NET中所添加的一組類別庫，這組類別庫可以使用Model-View-Controller的設計模式來開發ASP.NET的應用程式。它與現有的ASP.NET應用程式並沒有衝突，所以兩者是可以並行的。ASP.NET MVC Framework被包裝在System.Web.Mvc.dll中，並利用ASP.NET Routing來支援動作流以及URL Rewriting的能力，讓它可以更貼近Web的發展以及Web 2.0的特性。對於多數有ASP開發經驗的開發人員來說看起來比較不陌生，但對於沒有接觸過像ASP、PHP、JSP、Perl這些Web開發工具的開發人員來說，相對的不容易入門。ASP.NET MVC 的第一個版本於2009年3月17日釋出RTM版本，最新的ASP.NET MVC 5.2則是於2014年12月24日正式發行。
微軟於 ASP.NET Core 中提出下一代的 MVC 框架，稱為 ASP.NET Core MVC。

**原理**
ASP.NET MVC是遵循軟體模式的Model-View-Controller來發展，其中Model指的是資料或是業務邏輯元件，View是呈現給使用者看的資訊，而Controller則是接取來自使用者的指令與資料，並將Model與View做整合的控制器，當伺服器接到對ASP.NET MVC應用程式的要求時，伺服器（IIS）會先使用UrlRoutingModule(ASP.NET Routing的 HTTP 模組)，由它來解析是否有包含ASP.NET MVC應用程式的URL，若有，則會產生一個MvcRouteHandler物件，這個物件會裝載執行的必要資訊，並且會呼叫包含在URL中的Controller的Execute方法來執行工作。
Controller物件是基於IController介面的規則所定義，提供針對HTTP要求做回應的一個執行工具，在ASP.NET MVC中已實作一個預設的類別 Controller，提供了必要的基礎功能，另外也發展了一個 Controller 工廠，稱為 Controller Factory，以IControllerFactory介面定義，亦提供了DefaultControllerFactory，開發人員可以利用基本的類別以及利用它們來衍生自己的 Controller 或 Controller Factory 來實作自己的控制器邏輯功能。
Model物件則是為ASP.NET MVC提供資料，不過它沒有基礎類別，而是使用.NET Framework一般性的資料結構或是現在的ADO.NET資料物件，像是List、Dictionary、DataTable、DataReader與DataSet等等，當然也可以是自己開發的商業物件，這些資料會透過ASP.NET MVC的ModelBinder工具類別來與Controller整合，ModelBinder本身是支援泛型(Generic)的，因為各種型別的資料它都可以使用。在ASP.NET MVC中提供了一個DefaultModelBinder物件，可支援大多數的.NET Framework資料型別，以及陣列和已實作像是IList、IDictionary以及ICollection等介面的物件。
Model會在Controller執行動作時，作為一個ActionResult物件方式傳回給MvcHandler物件，而這個物件即會指定要顯示的View物件，像是下列程式碼所示：
using System.Linq;
using System.Web.Mvc;
using System.Web;
using System;
// GET: /Person/
public ActionResult Index()
{
return View(people);
}
// GET: /Person/Details/5
public ActionResult Details(Person person)
{
return View(person);
}
// GET: /Person/Create
public ActionResult Create()
{
return View();
} 
// POST: /Person/Create
AcceptVerbs(HttpVerbs.Post)
public ActionResult Create(Person person)
{
if (!ModelState.IsValid)
{
return View("Create", person);
}
people.Add(person);
return RedirectToAction("Index");
}
Public Class HomeController
Inherits System.Web.Mvc.Controller

'GET: /Person/
Function Index() As ActionResult
Return View(people)
End Function
'GET: /Person/Details/5
Function Details(Person person) As ActionResult
Return View(person)
End Function

'GET: /Person/Create
Function Create() As ActionResult
Return View()
End Function
'POST: /Person/Create

Function Contact() As ActionResult
If ModelState.IsValid Then
Return View("Create", person)
Else
people.Add(person)
Return RedirectToAction("Index")
End If
End Function
End Class
View物件以IView與IViewDataContainer等介面為主，並且以ASP.NET的各式前端介面為主要輸出工具，基於MVC的View彈性化設計考量，以往在ASP.NET Web Form的程式碼與HTML分離模式將不再存在，而是將程式碼與HTML混合的方式設計，讓開發人員可以更精確的對View進行控制，而目前 ASP.NET MVC 支援的 View 有下列幾種：- .aspx網頁，由ViewPage來支援。- .ascx使用者控制項，由ViewUserControl來支援。- .master主版頁面，由ViewMasterPage來支援。
每個 View 物件都會內含一個泛型的參數，用來裝載要呈現的資料(即Model)，然後使用類似下面的方式來呈現資料：





My MVC Application


















**技術**
在ASP.NET MVC架構中，除了Controller、Model與View三個主要部份以外，還包含了許多技術以讓這三層得以整合並交互運作。

**Controller**
Controller在ASP.NET MVC應用程式中是負責中控的角色，也是來自用戶端HTTP要求的處理核心，因此有許多處理與轉向HTTP要求的輔助技術在Controller層次都會使用到。

**ASP.NET 路由技術**
用來過濾用戶端要求的URL，並藉由定義好的路由表(route table)將要求導向至正確的MVC Controller，並呼叫Controller中的Execute方法執行，而Execute方法會將HTTP動作以及實際執行的指令交給正確的函式來執行。而通常一個MVC應用程式的URL都會是類似這樣的URL格式：
http://127.0.0.1/ControllerName/ActionName/ActionParameters
而MvcRouteHandler會拆解URL，找出目標的Controller，並且將ActionName以及ActionParameters傳給Controller中負責的函式（以ActionName來指定）。例如下列的URL會傳遞給BlogController的GetList方法：
http://127.0.0.1/Blog/GetList

**動作與方法直接整合**
ASP.NET MVC利用了中介資料的技術，直接將方法對應到指定的 HTTP 動詞 (GET/POST/PUT/DELETE/HEAD等)，MvcHandler會判斷要求的類別，並將它交給URL中指定的方法來處理。目前MVC Framework可用下列的方式指定（均包含在 HttpVerbs 列舉型別中）：- HttpVerbs.Get- HttpVerbs.Post- HttpVerbs.Delete- HttpVerbs.Put- HttpVerbs.Head

**將資料模型與展示層直接包裝**
ViewPage、ViewMasterPage、ViewUserControl等展示物件都支援泛型物件，可以直接裝載Model資料傳遞至前端輸出，可簡化處理Model與View之間整合的動作，只要一個參數就可以將資料傳給View：
public ActionResult GetList()
{
return View(BlogDataModel);
}
Function GetList() As ActionResult
Return View(BlogDataModel)
End Function

**Model**
在 ASP.NET MVC 中，Model 相對不設限，可以使用內建的資料結構以及自訂的資料類別，也可以是一個商業物件，因此 Model 的彈性相當大，除了前述的資料結構外，微軟新發展的一些資料存取方式也可以應用在 Model 中，像是ADO.NET Entity Framework與LINQ to SQL等技術。
另外，MVC在伺服端資料驗證中，提供了ViewDataDictionary類別，這個類別中有一個ModelState屬性，內含了ModelStateDictionary類別，開發人員可以利用這個類別來控制資料驗證的結果，而View中輸出驗證訊息的部份會和此類別有關聯，例如下列的程式：
AcceptVerbs(HttpVerbs.Post)
public ActionResult Create(Person person)
{
if (person.Name.Trim().Length == 0)
{
ModelState.AddModelError("Name", "Name is required.");
}
if (person.Age  200)
{
ModelState.AddModelError("Age", "Age must be within range 1 to 200.");
}
if ((person.Zipcode.Trim().Length > 0) && (!Regex.IsMatch(person.Zipcode, @"^\d{5}$|^\d{5}-\d{4}$")))
{
ModelState.AddModelError("Zipcode", "Zipcode is invalid.");
}
if (!Regex.IsMatch(person.Phone, @"((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}"))
{
ModelState.AddModelError("Phone", "Phone number is invalid.");
}
if (!Regex.IsMatch(person.Email, @"^\w-\.+@(\w-+\.)+\w-{2,4}$"))
{
ModelState.AddModelError("Email", "Email format is invalid.");
}
if (!ModelState.IsValid)
{
return View("Create", person);
}
people.Add(person);
return RedirectToAction("Index");
}
在 ASP.NET MVC 2.0 中，新增了一個可以直接讓 MVC Framework 針對資料欄位進行驗證控制的模型，稱為 Model Validation，它融合了在 .NET Framework 3.5 SP1 發表的 ASP.NET Dynamic Data Framework 中 Data Annotations (資料記號) 的特性，讓開發人員可以只利用標記的方式來執行驗證，或是利用自訂的程式碼來擴充資料記號的驗證行為。
using System.ComponentModel.DataAnnotations;  
namespace MvcDA {
MetadataType(typeof(ProductMD))
public partial class Product {
public class ProductMD {
StringLength(50),Required
public object Name { get; set; }
StringLength(15)
public object Color { get; set; }
Range(0, 9999)
public object Weight { get; set; }
//  public object NoSuchProperty { get; set; }
}
}
}

**View**
由於View是直接呈現給使用者，因此與使用者互動的部份都要由此層處理，包含資料的輸出以及以用戶端操作為主的回應（例如指令碼）等。

**HTML 工具類別**
HTML工具類別在View中是很重要的輸出工具，它內建了輔助產生HTML標籤的工具方法，多數的HTML語法都可以利用它來產生，包含像連結()、表單()以及表單控制項等等。HTML工具是以HtmlHelper類別為核心，並配合System.Web.Mvc.Html命名空間的方法，以延伸方法(Extension Method)的方式，讓產生HTML的程式就有如呼叫方法般簡單：
Index



Id


Name















**資料驗證**
View的HTML工具可以配合Model處理資料驗證的結果，在ASP.NET中常用的ValidationSummary在這裡也支援，而且MVC的架構讓驗證資訊的輸出也更加彈性：
Create

Fields

Name:
Required



Age:
Required



Street:




City:




State:




Zipcode:




Phone:
Required



Email:
Required








**不同類型的輸出**
每一個Controller中負責回應的方法，都會回傳一個ActionResult物件的資訊，ActionResult是一個執行結果物件的封裝體，當MvcHandler執行完指令接到ActionResult時，就會依照它的內容來輸出資料。目前MVC Framework支援的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 的路徑。
透過多類型的ActionResult，開發人員可以自由決定要回傳的資料的類型與格式。

**應用**
目前微軟有一個Oxite專案，是使用ASP.NET MVC Framework所開發的部落格引擎，而這個專案已經被微軟的部份應用平臺所採用，像是MIX Online、PDC 2009、MIX Video等官方網站都採用它來開發。另外，stackoverflow.com以及codeplex.com這兩個網站也是採用ASP.NET MVC Framework。

**版本歷程**

**授權**
ASP.NET MVC Framework雖然是ASP.NET的一部份，不過它的原始碼是透過Microsoft Public License (MS-PL)的授權模式公開，因此在MS-PL授權的範圍內，任何人是可以去檢視與修改它的原始碼的。

**ASP.NET MVC Razor Engine**
微軟在2010年7月2日由Scott Guthrie發表新的MVC繪製引擎 (Render Engine)：Razor Engine，它已內建於 ASP.NET MVC 3.0 中發布，它具有下列功能：
# 更輕量化且直覺的語法，減少在 View 中輸出資料時使用的語法，讓 View 的指令更加簡潔，例如使用 "@" + 變數名稱 的方式，就可以輸出程式中的變數，不必再用  來設定。如果程式有多行，可以使用 @{ } 的方式來設定。 
# 容易學習。
# 可相容於現在的程式語言 (ex: C#)。
# 透過 Visual Studio，可享有 Intellisense 能力。
# 可混用 HTML 與程式語言指令。
# 可用各種不同的文字編輯器編輯。
# 具有單元測試的能力。

**參考資料**

**外部網站**
  ASP.NET MVC 官方網站date=20090829085907 -  MSDN ASP.NET Virtual Labsdate=20090831105004 -  ASP.NET MVC Documentationsdate=20090907064548 

**View engines**
 MvcContribdate=20101126064140 - StringTemplate View Enginedate=20100814211922 - Sparkdate=20101205144618 - NDjangodate=20101201235542 - Naked Objects MVCdate=20100919111402 - Razordate=20101110065355 （預計ASP.NET MVC 3.0導入）