1.理解控制器
MVC控制器負責響應對ASP.NET MVC網站發起的請求。每一個瀏覽器請求都映射到了一個專門的控制器。舉個例子,設想一下你在瀏覽器地址欄輸入了下面的URL:
localhost/product/index/3
在這種情況下,將會調用一個名為ProductController的控制器。ProductController負責產生對瀏覽器請求的響應。舉個例子,控制器可能會返回一個特定的視圖,或者是將使用者重新導向到另一個控制器。
你可以通過在ASP.NET MVC應用程式的Controllers檔案夾下添加一個新的控制器來建立一個新控制器。右鍵點擊控制器的檔案夾,並且選擇功能表項目“Add(添加)”,“New(建立項)”,並選擇“MVC Controller Class(MVC控制器類)”(見圖1)。控制器的名字必須含有Controller尾碼。舉個例子,控制器名稱ProductController沒什麼問題,但是控制器Product就不起作用。
如果你建立一個新的名為ProductController的控制器,那麼你將會獲得代碼清單1所示的檔案。
代碼清單1 – ProductController.cs
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;namespace MvcApp.Controllers{ public class ProductController : Controller { public ActionResult Index() { // Add action logic here throw new NotImplementedException(); } }}
如同你在代碼清單1中所看到的,控制器不過是一個類(Visual Basic.Net 或者是C#類)。一個控制器是一個繼承自System.Web.Mvc.Controller基類的類。因為控制器繼承自這個基類,所以控制器輕鬆地繼承了一些有用的方法(我們不久將會討論這些方法)。
2. 理解控制器動作
控制器暴露出控制器動作。動作是控制器的一個方法,當你在瀏覽器地址欄輸入某一特定的URL時,將會調用這個方法。舉個例子,假設你對下面這個URL發出請求:
localhost/Product/Index/3
在本例中,Index()方法在ProductController類上被調用。Index()方法是控制器動作的一個例子。
一個控制器動作必須是控制器類的一個公用方法。C#方法,預設時,是私人方法。意識到你添加到控制器類中的任何公用方法都會自動被暴露為控制器動作(你必須非常小心,因為控制器動作可以被全球的任何人調用,僅僅簡單地通過在瀏覽器地址欄輸入正確的URL)。
控制器動作還要滿足一些額外的需求。作為控制器動作來使用的方法不能夠重載。另外,控制器動作不能為靜態方法。除了這些以外,你可以將任何方法作為控制器動作來使用。
3. 理解控制器結果
控制器動作返回一種叫做動作結果(Action Result)的東西。動作結果是控制器動作返回給瀏覽器請求的東西。
ASP.NET MVC架構支援六種標準類型的動作結果:
ViewResult – 代表HTML及標記。
EmptyResult – 代表無結果。
RedirectResult – 代表重新導向到一個新的URL。
RedirectToRouteResult – 代表重新導向到一個新的控制器動作。
JsonResult – 代表一個JSON(Javascript Object Notation)結果,它可以用於AJAX應用程式。
ContentResult – 代表著文本結果。
所有這些動作結果都繼承自ActionResult基類。
在大多數情況下,控制器動作 ViewResult。例如,代碼清單2中的Index()控制器動作返回了一個ViewResult。
代碼清單2 – BookController.cs
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;namespace MvcApp.Controllers{ public class BookController : Controller { public ActionResult Index() { return View(); } }}
當一個動作返回一個ViewResult,將會向瀏覽器返回HTML。代碼清單2中的Index()方法向瀏覽器返回了一個名為Index.aspx的視圖。
注意到代碼清單2中的Index()動作並沒有放回一個ViewResult()。而是調用了Controller基類的View()方法。通常情況下,你並不直接返回一個動作結果。而是調用Controller基類的下列方法之一:
View – 返回一個ViewResult結果。
Redirect – 返回一個RedirectResult 動作結果。
RedirectToAction – 返回一個RedirectToAction動作結果。
RedirectToRoute – 返回一個RedirectToRoute動作結果。
Json – 返回一個JsonResult動作結果。
Content – 返回一個ContentResult動作結果。
因此,如果你想向瀏覽器返回一個視圖,你可以調用View()方法。如果你想要降使用者從一個控制器動作重新導向到另一個,你可以調用RedirectToAction()方法。舉個例子,代碼清單3中的Details()動作要麼顯示一個視圖,要麼將使用者重新導向到Index()動作,取決於Id參數是否含有值。
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;namespace MvcApp.Controllers{ public class CustomerController : Controller { public ActionResult Details(int? Id) { if (Id == null) return RedirectToAction("Index"); return View(); } public ActionResult Index() { return View(); } }}
ContentResult動作結果很特別。你可以使用ContentResult動作結果來將動作結果作為純文字返回。舉個例子,代碼清單4中的Index()方法將訊息作為了純文字返回,而不是HTML。
代碼清單4 – StatusController.cs
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;namespace MvcApp.Controllers{ public class StatusController : Controller { public ContentResult Index() { return Content("Hello World!"); } }}
當調用StatusController.Index()動作時,並沒有返回一個視圖。而是向瀏覽器返回了原始的文本“Hello World!”。
如果一個控制器動作返回了一個結果,而這個結果並非一個動作結果 – 例如,一個日期或者整數 – 那麼結果將自動被封裝在ContentResult中。舉個例子,當調用代碼清單5中的WorkController的Index()動作時,日期將自動作為一個ContentResult返回。
代碼清單5 – WorkerController.cs
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;namespace MvcApp.Controllers{ public class WorkController : Controller { public DateTime Index() { return DateTime.Now; } }}
代碼清單5中的Index()動作返回了一個DateTime對象。ASP.NET MVC架構自動將DateTime對象轉換為一個字串,並且將DateTime值封裝在一個ContentResult中。瀏覽器將會以純文字的方式收到日期和時間。
4. 總結
這篇教程的目的是為你介紹ASP.NET MVC中控制器、控制器動作以及控制器動作結果的概念。在第一部分,你學習了如何向ASP.NET MVC項目中添加新的控制器。接下來,你學習了控制器的公用方法是如何作為控制器動作暴露給全世界的。最後,我們討論了動作結果的各種不同類型,這些動作結果可以從控制器動作中返回。特別地,我們討論了如何從控制器動作中返回一個ViewResult、RedirectToActionResult和ContentResult。
5. 建立控制器
這篇教程的目的是解釋如何來建立新的ASP.NET MVC控制器。你會學習如何通過Visual Studio Add Controller菜單和手工建立類檔案,來建立控制器。
5.1 使用Add Controler菜單選項
建立一個新控制的最簡單方法是在Visual Studio的解決方案瀏覽器的Controllers檔案夾上點擊右鍵,並且選擇Add,Controller功能表項目(1)。選擇這個功能表項目開啟了Add Controller對話方塊(2)。
圖2:添加一個新的控制器
注意到控制器名稱的第一部分在Add Controller對話方塊中高亮顯示了。每一個控制器的名稱必須以Controller尾碼結尾。舉個例子,你可以建立一個叫做ProductController的控制器,但是不能建立一個叫做Product的控制器。
NOTE:如果你建立一個控制器,它不含有Controller尾碼,那麼你將無法調用這個控制器。不要這麼做 -- 在犯了這個錯誤之後,我已經浪費了不計其數的時間。
代碼清單1 - Controller/ProductController.cs
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using System.Web.Mvc.Ajax;namespace MvcApplication1.Controllers{ public class ProductController : Controller { // // GET: /Product/ public ActionResult Index() { return View(); } }}
你應該總是在Controllers檔案夾中建立控制器。否則的話,就破壞了ASP.NET MVC的慣例,其他的程式員將會花費更多艱辛的時間來理解你的應用程式。
5.2 建立動作方法
當你建立一個控制器時,你可以選擇自動產生Create,Update和Details動作方法(3)。如果你選擇了這個選項,那麼會產生代碼2中的控制器類。
代碼清單2 - Controllers\CustomerController.cs
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using System.Web.Mvc.Ajax;namespace MvcApplication1.Controllers{ public class CustomerController : Controller { // // GET: /Customer/ public ActionResult Index() { return View(); } // // GET: /Customer/Details/5 public ActionResult Details(int id) { return View(); } // // GET: /Customer/Create public ActionResult Create() { return View(); } // // POST: /Customer/Create [AcceptVerbs(HttpVerbs.Post)] public ActionResult Create(FormCollection collection) { try { // TODO: Add insert logic here return RedirectToAction("Index"); } catch { return View(); } } // // GET: /Customer/Edit/5 public ActionResult Edit(int id) { return View(); } // // POST: /Customer/Edit/5 [AcceptVerbs(HttpVerbs.Post)] public ActionResult Edit(int id, FormCollection collection) { try { // TODO: Add update logic here return RedirectToAction("Index"); } catch { return View(); } } }}
這些產生的方法都只是一些存根方法(stub methods)。你必須自己為客戶的建立、更新和顯示詳情添加實際的邏輯。但是,這些存根方法為你提供了一個漂亮的著手點。
5.3 建立一個控制器類
ASP.NET MVC控制器不過是一個類。如果你喜歡,可以無視Visual Studio便利的控制器建立方式,自己手動來建立一個控制器類。按照這些步驟:
右鍵點擊Controllers檔案夾,並且選擇功能表項目Add,New Item,然後選擇Class模板。
將新類命名為PersonController.cs,然後點擊Add按鈕。
修改產生的類檔案,讓這個類繼承自System.Web.Mvc.Controller基類(見代碼清單3)。
代碼清單3 - Controllers\PersonController.cs
using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace MvcApplication1.Controllers{ public class PersonController : System.Web.Mvc.Controller { public string Index() { return "Hello World!"; } }}
代碼清單3中的控制器類公布了一個叫做Index()的動作,它返回字串“Hello World!”。你可以通過運行應用程式,並且請求像下面這樣的URL來調用這個控制器動作:
localhost:40071/Person
NOTE:ASP.NET 程式開發伺服器使用一個隨機的連接埠號碼(例如,40071)。當輸入URL來調用控制器時,你需要提供正確的連接埠號碼。你可以通過將滑鼠移至上方在ASP.NET程式開發伺服器的表徵圖上來獲得連接埠號碼,該表徵圖位於Windows Notification Area(Windows通知區域,螢幕的右下角)。
6. 建立自訂動作
本篇教程的目的是解釋如何建立一個新的控制器動作。你會學習到控制器動作的要求。你還會學習如何來阻止將方法公布為控制器動作。
6.1 添加動作到控制器
你可以通過在控制器中添加一個新的方法,將新的動作添加到控制器中。舉個例子,代碼清單1中的控制器包含了一個叫做Index()和一個叫做SayHello()的動作。這兩個方法都公布為了動作。
代碼清單1 - Controllers\HomeController.cs
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;namespace MvcApplication1.Controllers{ [HandleError] public class HomeController : Controller { public ActionResult Index() { return View(); } public string SayHello() { return "Hello!"; } }}
為了將方法作為一個動作公布給全世界,方法必須滿足特定的要求:
方法必須是公用的。
方法不能是靜態方法。
方法不能使擴充方法。
方法不能是建構函式,訪問器,或者設定器。
方法不能擁有開放泛型型別(open generic types)。
方法不能使控制器基類中的方法。
方法不能含有ref或者out參數。
6.2 阻止公用方法被調用
如果你需要在控制器中建立一個公用方法,但是你不想將這個方法發布為控制器動作,那麼你可以通過使用[NonAction]特性來阻止該方法被外界調用。舉個例子,代碼清單2中的控制器含有一個叫做CompanySecrets()的公用方法,它使用[NonAction]特性進行了修飾。
代碼清單2 - Controller\WorkController.cs
using System.Web.Mvc;namespace MvcApplication1.Controllers{ public class WorkController : Controller { [NonAction] public string CompanySecrets() { return "This information is secret."; } }}
如果你試圖通過在瀏覽器地址欄輸入/Work/CompanySecrets來調用CompanySecrets()控制器動作,那麼你會獲得圖5所示的錯誤訊息:
【相關推薦】
1. 什麼是ASP.NET MVC ?總結ASP.NET MVC
2. 深入瞭解ASP.NET MVC與WebForm的區別
3. 詳細介紹ASP.NET MVC--視圖
4. 詳細介紹ASP.NET MVC--路由
5. 通過asp.net mvc開發自訂菜單編輯工具的程式碼範例