《Pro ASP.NET MVC 3 Framework》學習筆記之二十二【Controllers和Actions】


Controllers入門(Introducing the Controller)

每一個針對應用程序的請求都是通過Controller處理的,controller自由地選擇合適的方式來處理這些請求,只要它不偏離到View和Model所負責的區域。這樣意味着我們不要把業務或數據存儲的邏輯放到Controllers里面,也不要創建用戶接口。

在ASP.NET MVC框架里面,Controllers是包含必要的處理請求的.NET類。前面有解釋Controller的角色是封裝我們的應用程序邏輯。這意味着Controller是負責處理請求,實行對Model的操作,選擇View呈現給用戶。本次的筆記會介紹Controllers是怎樣被實現的以及我們能夠接收和創建輸出的不同方式。

MVC框架本身並沒有限定我們通過View創建HTML,並且會討論其他可用的選擇。同時也會展示Actions方法是如何讓單元測試變得簡單,以及闡釋怎樣測試每一種由Actions產生的Results。

下面通過新建一個Project來說明,創建一個ControllersAndActions的項目,選擇Empty Template.

1.創建一個實現IController的Controller

在MVC框架里面,Controller類必須實現IController接口:如下

public interface IController { void Execute(RequestContext requestContext); }

這是一個非常簡單的接口,只有一個Execute方法,當一個請求在Controller類里面被命中時調用。MVC框架通過讀取由routing data創建的Controller屬性的值來知道哪一個Controller類被命中。我們能夠通過實現IController接口來創建一個Controller類,但是這是非常低級的接口,並且我們要做很多的工作來讓Controller變成可用的。

下面的BasicController提供了一個展示。

View Code
namespace ControllersAndActions.Controllers
{
public class BasicController:IController
{
public void Execute(RequestContext requestContext)
{
string controller = (string)requestContext.RouteData.Values["controller"];
string action = (string)requestContext.RouteData.Values["action"];
requestContext.HttpContext.Response.Write(string.Format("Controller:{0},Action:{1}", controller, action));
}
}
}

在上面的Execute方法里面,我們從關聯請求的RouteData對象里面讀取了controller和action變量的值並寫入了輸出的結果里面。這時如果我們運行程序並輸入:
/Basic/Index,會顯示如下:

通過實現IController接口能夠讓我們創建一個類,這個類是被MVC框架識別為Controller並發送請求給它的。但是要寫一個負責的應用程序,這就變得非常艱難。MVC框架不具體到一個controller是如何處理請求的,這也意味着我們能夠創建任何方法。

2.創建一個繼承Controller類的Controller

MVC框架是無限制地可定制和看擴展的,我們能夠實現IController接口創建任何一種我們需要的請求處理和結果生成的Controller類.如果我們不想操作方法,不想關注呈現的視圖,那么我們可以把一切事情掌握在自己手里並寫出一個更好的,更快的,更加優雅的處理請求的方式,或者我們也可以將controller從System.Web.Mvc.Controller派生,這樣就可以使用MVC框架提供的功能。

System.Web.Mvc.Controller類提供了三個關鍵的功能:

①Action Methods:一個controller類的行為會划分到多個方法里面,每一個方法暴露給不同的URL並使用從請求中提取的參數來調用,這些方法稱為Action Methods。
②Action Results:Action Methods的返回值
③Filters:封裝一些可重用的行為,使用時只需要在controller和action方法上面添加[Attributes]。

接下來,創建一個DerivedController類並繼承Controller,如下:

View Code
    public class DerivedController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Hello from DerivedController Index Method";
return View("Index");
}
}

接收輸入(Receiving Input)

Controller需要頻繁的訪問傳入進來的數據,比如querystring,通過路由系統解析參數的值等等。有三種主要的方式來訪問這樣的數據:

①從context對象提取  ②作為參數傳遞給action方法的  ③明確的調用框架的模型綁定功能

ps:參數名是忽略大小寫的,如Request.Form["City"]跟Request.Form["city"]是一樣的。

這里我們主要用前面兩種方式,模型綁定會在后面的章節介紹。

1.從Context對象獲取數據
當我們創建一個從Controller基類派生的controller時,我們就能夠訪問一套非常便捷的屬性,這些屬性包括:Request,  Response ,  RouteData,  HttpContext, Server
每一個屬性提供請求的一個方面的信息,這些屬性都是在ControllerContext實例里面的。在action方法里面是可以使用任何context對象來訪問這些屬性的,例如:

View Code
        public ActionResult RenameProduct()
{
//僅僅為了演示部分屬性
string userName = User.Identity.Name;
string serverName = Server.MachineName;
string clientIP = Request.UserHostAddress;
DateTime dateStamp = HttpContext.Timestamp;
string oldProductName = Request.Form["OldName"];
string newProductName = Request.Form["NewName"];
return View("Index");
}

2.使用Action方法的參數
這種方式比上一種方式要優雅,它讓我們的Action方法更易讀,下面是一個對比:

View Code
//顯示天氣預備
public ActionResult ShowWeatherForecast(){
string city = RouteData.Values["city"];
DateTime forDate = DateTime.Parse(Request.Form["forDate"]);
//實現部分...
}
//我們可以重寫下
public ActionResult ShowWeatherForecast(string city, DateTime forDate){
//實現部分
}
//下面這種方式是不是比上面的要優雅易讀呢?

其實不僅僅是易讀而且有利於單元測試,有一點需要我們注意,action方法里面不允許有ref或out型的參數,這個編譯時不會報錯,但是運行會拋異常。如下面的實例:

        public ActionResult Index(out int a)
{
ViewBag.Message = "Hello from DerivedController Index Method";
a = 1;
ViewBag.Num = a;
return View("Index");
}

Index視圖里面的代碼如下:

View Code
@{
ViewBag.Title = "MyView";
}
<h2>
MyView</h2>
Message:@ViewBag.Message<br />
Num:@ViewBag.Num

運行拋如下異常:

理解參數對象是怎樣被實例化的

Controller基類使用MVC框架的Value Providers(值提供程序)和Model Binders(模型綁定)兩個組件來獲取action方法參數的值
Value Providers將可用的數據項集合呈現給controller,有內置的value providers從Request.Form,  Request.QueryString,  Request.Files,RouteData.Values獲取數據項。然后這些值會被傳遞給模型綁定(Model Binders)——將這些值映射到action方法需要的參數的類型。默認的model binders能夠創建和填充任何.NET類型的對象,並包含自定義的類型和集合。

理解可選和必須的參數

如果MVC框架不能找到一個引用類型參數的值,action方法仍然會被調用,但是使用的null值。如果是一個值類型的值沒有找到,那么會發生異常並且action方法不會被調用。

①值類型的從參數是必須的被賦值的。如果想讓這個跟引用類型一樣,可以這樣定義int?,當依然沒有找到值時,不會發生異常,而是會傳遞null值。
②引用類型的參數是可選的。為了讓它變成必選的(保證一個非空的值被傳遞),在action方法的上面添加一些代碼拒絕null值

指定默認參數的值

如果我們要處理不包含action方法參數值的請求,但是又不想去檢查null值。這時可以使用C#可選參數的特性,如下:
public ActionResult Search(string query="all",int page=1){...}

今天的筆記就到這里,后面一篇筆記還是關於這部分的內容。筆記里面不對的地方還請路過的朋友指正,謝謝!
晚安!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM