深入了解ASP.NET MVC5的Controller核心原理及扩展(2)

三、创建一个自定义的Action Invoker

一旦Controller Factory创建了一个Controller的实例,mvc框架需要最终一种方式来调用这个实例的Action。如果你创建Controller类是继承于基类Controller,都不用关心这些,因为基类Controller自己就包含一个Action Invoker负责调用Action,响应请求。Action Invoker是对接口IActionInvoker的实现。下面看看IActionInvoker定义了哪些方法:

 
  1. namespace System.Web.Mvc {
  2. public interface IActionInvoker {
  3. bool InvokeAction(ControllerContext controllerContext, string actionName);
  4. }
  5. }
可以看出这个IActionInvoker中有一个方法:InvokeAction,它有两个参数Controller上下文和action的名字,返回值是bool,当返回false表示没有找到对应的action。下面我们自己来实现一个ActionInvoker:
 
  1. using System.Web.Mvc;
  2. namespace ControllerExtensibility.Infrastructure {
  3. public class CustomActionInvoker : IActionInvoker {
  4. public bool InvokeAction(ControllerContext controllerContext,
  5. string actionName) {
  6. if (actionName == "Index") {
  7. controllerContext.HttpContext.
  8. Response.Write("This is output from the Index action");
  9. return true;
  10. } else {
  11. return false;
  12. }
  13. }
  14. }
  15. }
当actionName为Index的时候,直接通过Response输出一段文字到浏览器。action invoker是包含在一Controller里面的,具体可以通过属性Controller.ActionInvoker来设置,因此不同的Controller可以设置不同的 action invoker。下面我们演示一下 Controller.ActionInvoker的自定义:
 
  1. using ControllerExtensibility.Infrastructure;
  2. using System.Web.Mvc;
  3. namespace ControllerExtensibility.Controllers {
  4. public class ActionInvokerController : Controller {
  5. public ActionInvokerController() {
  6. this.ActionInvoker = new CustomActionInvoker();
  7. }
  8. }
  9. }
可以看到上面我们定义的ActionInvokerController一个Action方法都没有,我们在类的构造函数中设置了这个Controller的 ActionInvoker 为我们自定义的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

 
  1. using ControllerExtensibility.Models;
  2. using System.Web.Mvc;
  3. namespace ControllerExtensibility.Controllers {
  4. public class CustomerController : Controller {
  5. public ViewResult Index() {
  6. return View("Result", new Result {
  7. ControllerName = "Customer",
  8. ActionName = "Index"
  9. });
  10. }
  11. [ActionName("Enumerate")]
  12. public ViewResult List() {
  13. return View("Result", new Result {
  14. ControllerName = "Customer",
  15. ActionName = "List"
  16. });
  17. }
  18. }
  19. }
这样我们请求这个Action就要用:/Customer/Enumerate这个路径来访问。除了上面ActionName来改名字,还有以下其它内置的Action筛选:


1、[NonAction] :标示不是Action方法

2、[HttpPost]:标示当请求是Post提交才调用

4.1、自定义一个Action筛选

Action筛选都是继承于抽象类ActionMethodSelectorAttribute:

 
  1. using System.Reflection;
  2. namespace System.Web.Mvc {
  3. [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
  4. public abstract class ActionMethodSelectorAttribute : Attribute {
  5. public abstract bool IsValidForRequest(ControllerContext controllerContext,
  6. MethodInfo methodInfo);
  7. }
  8. }
下面定义一个判断MVC是否是本地请求的Action筛选器:
 
  1. using System.Reflection;
  2. using System.Web.Mvc;
  3. namespace ControllerExtensibility.Infrastructure {
  4. public class LocalAttribute : ActionMethodSelectorAttribute {
  5. public override bool IsValidForRequest(ControllerContext controllerContext,
  6. MethodInfo methodInfo) {
  7. return controllerContext.HttpContext.Request.IsLocal;
  8. }
  9. }
  10. }
上面重写了 抽象类 ActionMethodSelectorAttribute的方法IsValidForRequest,当是本地请求就返回true。下面看看怎么使用这个自定义的MVC5的 Action筛选器
 
  1. [Local]
  2. public ActionResult LocalIndex() {
  3. return View("Result", new Result {
  4. ControllerName = "Home", ActionName = "LocalIndex"
  5. });
  6. }
这样中有是本地请求才会成功调用LocalIndex。

4.2、错误未知的Action的处理

当mvc5中的action invoker找不到一个对应的Action方法来调用,那么它的InvokeAction方法就会返回false。这时Controller类就会调用自身的HandleUnknownAction方法,默认情况会返回404错误到浏览器。这种机制是mvc程序中最普遍和最有用的,但是你也可以重写Controller的HandleUnknownAction方法,做一些自定义的操作:

 
  1. using System.Web.Mvc;
  2. using ControllerExtensibility.Infrastructure;
  3. using ControllerExtensibility.Models;
  4. namespace ControllerExtensibility.Controllers {
  5. public class HomeController : Controller {
  6. // ...other action methods omitted for brevity...
  7. protected override void HandleUnknownAction(string actionName) {
  8. Response.Write(string.Format("You requested the {0} action", actionName));
  9. }
  10. }
  11. }
这样当用户请求HomeController中一个不存在的Action时会输出一段字符串,而不是返回404。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值