概述
在MVC中,Controller用來處理和回應使用者的互動,選擇使用哪個View來進行顯示,需要往視圖中傳遞什麼樣的視圖資料等。ASP.NET MVC Framework中提供了IController介面和Controller基類兩種類型,其中在Controller提供了一些MVC中常用的處理,如定位正確的action並執行、為action方法參數賦值、處理執行過程中的錯誤、提供預設的WebFormViewFactory呈現頁面。IController只是提供了一個控制器的介面,如果使用者想自訂一個控制器的話,可以實現IController,它的定義如下:
public interface IController{ void Execute(ControllerContext controllerContext);}
定義控制器和action
在前面三篇的例子中,我們已經定義過了控制器,只要繼承於Controller就可以了:
public class BlogController : Controller{ [ControllerAction] public void Index() { BlogRepository repository = new BlogRepository(); List<Post> posts = repository.GetAll(); RenderView("Index", posts); } [ControllerAction] public void New() { RenderView("New"); }}
通過ControllerAction特性來指定一個方法為action,ControllerAction的定義非常簡單:
[AttributeUsage(AttributeTargets.Method)]public sealed class ControllerActionAttribute : Attribute{ public ControllerActionAttribute();}
使用強型別傳遞ViewData
通過前面的一些樣本,已經看到了一些樣本如何從控制器傳遞視圖資料給View,在Controller中,傳遞視圖資料到View,我們可以有兩種方式選擇,其中一種是使用強型別來傳遞視圖資料,如下範例程式碼:
[ControllerAction]public void Index(){ BlogRepository repository = new BlogRepository(); List<Post> posts = repository.GetAll(); RenderView("Index", posts);}
有朋友在回複中提到,如果想傳遞多個Model或者集合資料到View,該如何傳遞?這裡需要再定義一個類型:
public class HomeViewData{ public List<Post> Posts { get; set; } public List<Category> Categories { get; set; }}
然後在控制器中可以這樣進行傳遞資料:
[ControllerAction]public void Index(){ BlogRepository repository = new BlogRepository(); List<Post> posts = repository.GetAll(); List<Category> categories = repository.GetAllCategory(); HomeViewData viewData = new HomeViewData(); viewData.Posts = posts; viewData.Categories = categories; RenderView("Index", viewData);}
使用強型別類來傳遞視圖資料,有如下好處(來自於Scrottgu):
1.避免使用字串來查詢對象,得到對你的控制器和視圖代碼的編譯時間檢查
2.避免需要在使用象C#這樣的強型別語言中明確轉換ViewData對象字典中的值
3.在你的視圖網頁的標識檔案以及後台代碼檔案中得到你的ViewData對象的自動代碼intellisense
4.可以使用代碼重構工具來協助自動化對整個應用和單元測試程式碼程式庫的改動
使用ViewData字典來傳遞資料
在Controller基類中,有一個這樣的字典定義:
public IDictionary<string, object> ViewData { get; }
這樣我們可以直接把視圖資料通過ViewData欄位來傳遞,如下範例程式碼:
[ControllerAction]public void Index(){ BlogRepository repository = new BlogRepository(); List<Post> posts = repository.GetAll(); List<Category> categories = repository.GetAllCategory(); ViewData["posts"] = posts; ViewData["categories"] = categories; RenderView("Index");}
在試圖中,可以這樣來擷取視圖資料:
<div> <%foreach (Post post in (ViewData["posts"] as List<Post>)) { %> <div class="postitem"> <strong>Title</strong>:<%=Html.Encode(post.Title) %></br> <strong>Author</strong>:<%=Html.Encode(post.Author) %></br> <strong>PubDate</strong>:<%=Html.Encode(post.PubDate.ToShortDateString()) %></br> <strong>Content</strong>:<%=Html.Encode(post.Description) %></br> <%=Html.ActionLink("Edit", new {action="Edit", Id=post.Id })%> </div><br /> <% } %></div>
處理未知的Action
Controller類中包含了一個HandlerUnknownAction的方法:
protected internal virtual void HandleUnknownAction(string actionName);
它用來處理一些未知的Action,預設情況下將返回HTTP 404錯誤,如果想自訂該處理,可以覆寫該方法:
[ControllerAction]protected override void HandleUnknownAction(string actionName){ if (ShouldShowSearch(action) == true) { RedirectToAction("search", new { query = action }); return; } base.HandleUnknownAction(actionName);}
它用來處理當出現未知的Action時,跳轉向Search Action。
結束語
在本篇文章中,我們介紹了ASP.NET MVC Framework中的Controller,包括如何定義Controller及Action,通過強型別和視圖資料字典來傳遞視圖資料,以及自訂處理未知的Action等內容,希望對您有所協助。最後,插播一條小廣告:我在部落格園社區中建立了一個Web技術聯盟小組,歡迎大家加入:http://space.cnblogs.com/group/webdev/