仍是這張圖:框架
當ControllerFactory生成Controller實例後,這時就須要使用ActionInvoker來選擇調用一個合適的Action執行。ASP.NET MVC提供的基類Controller已經實現了ActionInvoker的功能。可是咱們能夠實現自定義的ActionInvoker來替代框架中提供的ActionInvoker。ide
首先一個ActionInvoker須要實現IActionInvoker接口:函數
public interface IActionInvoker { bool InvokeAction(ControllerContext controllerContext, string actionName) ; }
InvokeAction參數有兩個,其中controllerContext包含當前Controller信息和請求信息,而actionName則是用調用的action名。當函數找到一個合適的Action併成功調用時返回true,不然返回false。post
那咱們要怎樣才能使用自定義的ActionInvoker呢,Controller類給咱們提供了ActionInvoker屬性,因此咱們能夠經過設置該屬性讓MVC使用咱們的ActionInvoker:this
public class HomeController : Controller { public HomeController() { this.ActionInvoker = new MyActionInvoker(); } //....其餘代碼..... }
MVC中內置的ActionInvokerspa
上面也說了,基類Controller實現了ActionInvoker的功能,它使用的就是MVC內置的ActionInvoker-----ControllerActionInvoker。code
一個方法要被ControllerActionInvoker看成一個Action須要知足如下條件:orm
1.該方法的做用域必須爲publicblog
2.該方法不能是靜態方法接口
3.該方法不能是Controller基類的方法
4.該方法不能是構造函數
另外:若是方法是一個泛型方法,比且符合以上條件,則會在嘗試調用的時候拋出一個異常
默認的,ControllerActionInvoker會將與actionName相同的方法名的方法做爲Action,並調用。可是若是一個Controller中有多個同名的重載的方法時怎麼辦呢,咱們可使用ActionNameAttribute特性來設置Action別名:
public class HomeController : Controller { [ActionName("Enumerate")] public ActionResult List() { return View(); } }
這樣當咱們請求/home/enumerate 時,調用的Action就是List,但當咱們請求/home/list時,List將不會被調用,在這個例子中將返回404頁面。
除了別名,ControllerActionInvoker還使用了action method selection(選擇偏好)機制來處理如何選擇多個同名的方法,來看下面的代碼:
[HttpGet] public ViewResult MyAction(int? id) { return View(id); } [HttpPost] public ViewResult MyAction(Product product) { return View(product); }
這個你們應該都很清楚了,當get請求時調用的是MyAction(int? id),而post請求時調用的是MyAction(Product product)。這就是action method selection。
咱們能夠建立自定義的Action Method選擇器,來設定ControllerActionInvoker的選擇偏好。
public class ActionMethodSelectorAttribute : Attribute { public bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) { return controllerContext.HttpContext.Request.IsLocal; } }
選擇器須要有IsValidForRequest方法,當方法返回true時,表示符合偏好,會優先調用該方法。
ControllerActionInvoker未找到合適Action時的處理:
在這種狀況下將會調用Controller的HandleUnknowAction方法,這個方法將會顯示404頁面,可是咱們能夠重寫該方法以改變默認行爲:
protected override void HandleUnknownAction(string actionName) { Response.Write(string.Format("未發現你要找的Action: {0}", actionName)); }