系列目录

Action的定位

再次回到Controller的ExecuteCore方法,回到action调用的入口:

1
if (!ActionInvoker.InvokeAction(ControllerContext, actionName))

这里的ActionInvoker是个IActionInvoke,它无疑是负责了所有action的调用逻辑,MVC中默认实现这个接口的是ControllerActionInvoke。可以想象ControllerActionInvoke面临的第一个问题是如何找到与actionName对应的action。

首先,并不是所有的action都合法,需要符合下面条件:

1、Public,非static

2、非Controller或其基类定义的方法,比如ToString(),GetHashcode()

3、不能是特殊名字System.Reflection.MethodBase的IsSpecialName标志,例如构造函数,属性包装器,事件包装器

4、具有泛型参数的方法尽管会被认为是action,但框架试图执行这样的action时会只是抛出异常。

其次,MVC为action的查找过程设计了两种“选择器”

  • ActionNameSelectorAttribute
  • ActionMethodSelectorAttribute

如果对此比较迷茫的话,看了他们的派生特性,你也许就明白了:

我们常用ActionNameAttribute来“伪装”;用HttpPostAttributeHttpGetAttribute来说明某个action符合的特定的http行为;用NoAction隐藏我们不想“暴露给url”的方法…其实这些行为的原理便是利用MVC为我们提供的action选择的机制。下面这张图说明了这个过程的完成逻辑:

ContollerActionInvoker.InvokeAction在内部创建一个ReflectedControllerDescriptor,并调用其FindAction方法,这个对象的FindAction负责调用一个ActionMethodSelector对象实现上述逻辑,并在最后返回一个ReflectedActionDescriptor。 ActionMethodSelector对象故名思意,原理上用反射执行上述过程,执行的结果要么返回一个MethodInfo,要么返回null,要 么抛出异常。ReflectedControllerDescriptor对返回值判断,如果是null,则也返回null;如果是 MethodInfo,则将其包装成ReflectedActionDescriptor返回。对于外面的InvokeAction方法来说只要 ReflectedControllerDescriptor返回的ReflectedActionDescriptor为空就返回false,否则继 续。Controller负责对返回false的情况调用HandleUnknownAction,该方法默认产生404错误,我们可以重写它。

在回过头来看看上图的逻辑,不难得到这样一个事实:ActionNameSelectorAttribute优先于ActionMethodSelectorAttribute,ActionMethodSelectorAttribute优先于没有ActionMethodSelectorAttribute特性的方法

更多关于这部分源码的细节,可以参考:通过源代码研究ASP.NET MVC中的Controller和View(六)

MVC的内建过滤器

ActionDescriptor(ReflectedActionDescriptor)返回后,ContollerActionInvoker开始执行action,但是在执行action前还有一些额外的步骤,那就是过滤。以下四个是MVC内建的过滤接口:

  • IActionFilter
  • IAuthorizationFilter
  • IExceptionFilter
  • IResultFilter

这四个Filter会被ControllerActionInvoker框架综合考量,下面的伪代码说明了ControllerActionInvoker处理他们的逻辑顺序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
try
{
    //依次执行IAuthorizationFilter
    Run each IAuthorizationFilter's OnAuthorization() method
    //所有的IAuthorizationFilter都返回null而不是ActionResult
    if(none of the IAuthorizationFilters cancelled execution)
    {
        Run each IActionFilter's OnActionExecuting() method
        Run the action method
        //注意到这里按照反转顺序进行
        Run each IActionFilter's OnActionExecuted() method (in reverse order)
        Run each IResultFilter's OnResultExecuting() method
        Run the action result
        //注意到这里按照反转顺序进行
        Run each IResultFilter's OnResultExecuted() method (in reverse order)
    }
    //有IAuthorizationFilter返回ActionResult
    else
    {
        Run any action result set by the authorization filters
    }
}
catch(exception not handled by any action or result filter)
{
    //注意到IExceptionFilter处理的异常只在这个try catch块中
    Run each IExceptionFilter's OnException() method
    Run any action result set by the exception filters
}

需要注意的事项,在代码中都已经给出注释,在后面一节中,将讨论其中的某些细节。

MVC中与这四个接口相关的特性如下:

我们熟悉的有AuthorizeOutputCacheChildAction等。曾经,对于这些形形色色的Attribute,我都不能很好的理解和归类,现在总算是找它们各自的归宿了。

下一节,将针对这四个过滤器接口深入讨论一些细节问题。

劳动果实,转载请注明出处:http://www.cnblogs.com/P_Chou/archive/2010/12/01/details-asp-net-mvc-07.html

深入理解ASP.NET MVC(7)的更多相关文章

  1. 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC

    系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递 七天学会ASP.NET MVC (三)— ...

  2. [转载]深入理解ASP.NET MVC之ActionResult

    Action全局观 在上一篇最后,我们进行到了Action调用的“门口”: 1 if (!ActionInvoker.InvokeAction(ControllerContext, actionNam ...

  3. 深入理解ASP.NET MVC Day1

    深入理解ASP.NET MVC   ASP.NET vs MVC vs WebForms 许多ASP.NET开发人员开始接触MVC认为MVC与ASP.NET完全没有关系,是一个全新的Web开发,事实上 ...

  4. 七天学会ASP.NET MVC ——深入理解ASP.NET MVC

    七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC   系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二) ...

  5. 深入理解ASP.NET MVC(6)

    系列目录 Action全局观 在上一篇最后,我们进行到了Action调用的“门口”: 1 if (!ActionInvoker.InvokeAction(ControllerContext, acti ...

  6. 深入理解ASP.NET MVC(5)

    系列目录 回顾 系列的前4节深入剖析了ASP.NET URL路由机制,以及MVC在此基础上是如何实现Areas机制的,同时涉及到inbound和outbound很多细节部分.第2节中提到MvcRout ...

  7. 深入理解ASP.NET MVC(目录)

    学ASP.NET MVC2有一段时间了,也针对性的做了个练习.感觉这个框架还是不错的,所以决定要深入系统的学习一下.看到这样一本书: 作者博客:http://blog.stevensanderson. ...

  8. 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 【转】

    http://www.cnblogs.com/powertoolsteam/p/MVC_one.html 系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会A ...

  9. [转载] ASP.NET MVC (一)——深入理解ASP.NET MVC

    个人认为写得比较透彻得Asp.net mvc 文章,所以转载过来,原文链接在最后: ASP.NET vs MVC vs WebForms 许多ASP.NET开发人员开始接触MVC认为MVC与ASP.N ...

  10. 理解ASP.NET MVC的路由系统

    引言 路由,正如其名,是决定消息经由何处被传递到何处的过程.也正如网络设备路由器Router一样,ASP.NET MVC框架处理请求URL的方式,同样依赖于一张预定义的路由表.以该路由表为转发依据,请 ...

随机推荐

  1. ‘’.join(列表)--列表转化为一个语句。 strip()删除掉str中的左右的空白字符

    1和2相比,删除掉了str左右的空白字符,2和3相比,删除掉了上下的空白字符

  2. input默认显示当前时间

    方法一: // 获取当天的年月日 new Date().getFullYear() + '-' + (new Date().getMonth() + 1) + '-' + new Date().get ...

  3. js--未来元素

    通过动态生成的标签,在生成标签直接绑定事件是无效的. eg:html标签 <div id="tree"> </div> <script> $(' ...

  4. Insert插入不同的列数量,统计信息对比

    一.实验目的: Insert插入表中相同的行数量,不同的列数量,通过10046 和autotrace工具对比查看逻辑读.物理读.time数据,并得出相应结论 二.测试 2.1测试流程: =>[为 ...

  5. Python3中的运算符

    一.Python3中的运算符 强调这是Python3中的运算符 +    加法 -     减法 *     乘法 /     除法 //    整除,只要整数部分 **   幂运算 %   取余数 ...

  6. 第8次Scrum会议(10/20)【欢迎来怼】

    一.小组信息 队名:欢迎来怼 小组成员 队长:田继平 成员:李圆圆,葛美义,王伟东,姜珊,邵朔,冉华 小组照片 二.开会信息 时间:2017/10/20 17:20~17:45,总计25min. 地点 ...

  7. Python算法——递归思想

    编程语言在构建程序时的基本操作有:内置数据类型操作.选择.循环.函数调用等,递归实际属于函数调用的一种特殊情况(函数调用自身),其数学基础是数学归纳法.递归在计算机程序设计中非常重要,是许多高级算法实 ...

  8. MySQL数据库一

    MySQL的基本命令: 进入数据库: mysql -u [username] -p[password]   (注:-u 和 用户名之间可以有空格 -p和password之间无空格)  mysql -u ...

  9. C++学习(一)之Visual Studio安装以及首次使用

    一.安装Visual Studio 首先下载Visual Studio 链接: http://pan.baidu.com/s/1pLhJt0Z 密码:uqyc 将.ios文件解压得到以下文件: 点击v ...

  10. [zoj4046][树状数组求逆序(强化版)]

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4046 题意:有一个含有n个元素的数列p,每个元素均不同且为1~n中的一个, ...