三、创建一个自定义的Action Invoker
一旦Controller Factory创建了一个Controller的实例,mvc框架需要最终一种方式来调用这个实例的Action。如果你创建Controller类是继承于基类Controller,都不用关心这些,因为基类Controller自己就包含一个Action Invoker负责调用Action,响应请求。Action Invoker是对接口IActionInvoker的实现。下面看看IActionInvoker定义了哪些方法:
- namespace System.Web.Mvc {
- public interface IActionInvoker {
- bool InvokeAction(ControllerContext controllerContext, string actionName);
- }
- }
- using System.Web.Mvc;
- namespace ControllerExtensibility.Infrastructure {
- public class CustomActionInvoker : IActionInvoker {
- public bool InvokeAction(ControllerContext controllerContext,
- string actionName) {
- if (actionName == "Index") {
- controllerContext.HttpContext.
- Response.Write("This is output from the Index action");
- return true;
- } else {
- return false;
- }
- }
- }
- }
- using ControllerExtensibility.Infrastructure;
- using System.Web.Mvc;
- namespace ControllerExtensibility.Controllers {
- public class ActionInvokerController : Controller {
- public ActionInvokerController() {
- this.ActionInvoker = new CustomActionInvoker();
- }
- }
- }
最后结果如下图:
四、使用MVC5自带的Action Invoker
上面我们演示了一个怎么在mvc5中自定义一个Action Invoker。但是不建议这样这样做,因为MVC5自带的Action Invoker为我们提供了比较强大和完善的实现。比如:包括视图关联特性。MVC5自带的Action Invoker类名为ControllerActionInvoker,要使用这个ControllerActionInvoker类Action方法必须要满足一下几个条件:
1、方法必须为public
2、方法不能为static
3、方法不能是System.Web.Mvc.Controller和System.Web.Mvc.Controller的基类的方法(如:ToString())
4、方法名不能够是同特殊意义名字(如:和类名一样)
默认情况,ControllerActionInvoker会在Controlller中去找与请求变量中Action的值一样的Action,比如:如果Action为值为Index,那么ControllerActionInvoker就会去对应Controller中找Action为Index的方法并调用它,响应请求。这种机制是MVC中用得最的情况,但是你也可以使用Action筛选器对Action的名字进行一些细致地调整。
使用一个自定义的Action Name
- using ControllerExtensibility.Models;
- using System.Web.Mvc;
- namespace ControllerExtensibility.Controllers {
- public class CustomerController : Controller {
- public ViewResult Index() {
- return View("Result", new Result {
- ControllerName = "Customer",
- ActionName = "Index"
- });
- }
- [ActionName("Enumerate")]
- public ViewResult List() {
- return View("Result", new Result {
- ControllerName = "Customer",
- ActionName = "List"
- });
- }
- }
- }
1、[NonAction] :标示不是Action方法
2、[HttpPost]:标示当请求是Post提交才调用
4.1、自定义一个Action筛选
Action筛选都是继承于抽象类ActionMethodSelectorAttribute:
- using System.Reflection;
- namespace System.Web.Mvc {
- [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
- public abstract class ActionMethodSelectorAttribute : Attribute {
- public abstract bool IsValidForRequest(ControllerContext controllerContext,
- MethodInfo methodInfo);
- }
- }
- using System.Reflection;
- using System.Web.Mvc;
- namespace ControllerExtensibility.Infrastructure {
- public class LocalAttribute : ActionMethodSelectorAttribute {
- public override bool IsValidForRequest(ControllerContext controllerContext,
- MethodInfo methodInfo) {
- return controllerContext.HttpContext.Request.IsLocal;
- }
- }
- }
- [Local]
- public ActionResult LocalIndex() {
- return View("Result", new Result {
- ControllerName = "Home", ActionName = "LocalIndex"
- });
- }
4.2、错误未知的Action的处理
当mvc5中的action invoker找不到一个对应的Action方法来调用,那么它的InvokeAction方法就会返回false。这时Controller类就会调用自身的HandleUnknownAction方法,默认情况会返回404错误到浏览器。这种机制是mvc程序中最普遍和最有用的,但是你也可以重写Controller的HandleUnknownAction方法,做一些自定义的操作:
- using System.Web.Mvc;
- using ControllerExtensibility.Infrastructure;
- using ControllerExtensibility.Models;
- namespace ControllerExtensibility.Controllers {
- public class HomeController : Controller {
- // ...other action methods omitted for brevity...
- protected override void HandleUnknownAction(string actionName) {
- Response.Write(string.Format("You requested the {0} action", actionName));
- }
- }
- }