仍是这张图:框架
当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)); }