系列目录

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. android小程序-电子钢琴-滑动连续响应

    原创文字,转载请标明出处: 利用Button实现简单地电子钢琴,可以简单地响应按钮的click事件来发出相应的声音.但是这样不能达到手指在屏幕滑动,而连续发声的效果,就像手指在真实钢琴按键上滑过一样. ...

  2. python基础题型一

    一.执行Python脚本的两种方式 #python name.py   Python解析器 #chmod +x name.py 二.简述位.字节的关系 1Byte=8bit 三.简述ascii.uni ...

  3. Python写一个批量生成账号的函数

    批量生成账户信息,产生的账户由@sina.com结尾,长度由用户输入,产生多少条也由用户输入,用户名不能重复,用户名必须由大写字母.小写字母和数字组成. def Users(num,len): # n ...

  4. Puppet的一些奇技淫巧

    puppet这个工具真的很神奇,先不说商业版有哪些黑科技,单是开源版本就有很多可能让你摸不着头脑的地方,下面来列举一下puppet是怎么查找puppet server的 其实很简单,puppet ag ...

  5. Javascript中的闭包 O__O "…

    一.闭包!? 闭包(closure)是Javascript语言的一个难点,对于初学者来说不容易理解,那我们先来看看闭包的含义. 百度百科与“官方”解释:所谓“闭包”,指的是一个拥有许多变量和绑定了这些 ...

  6. Strut2在Action-Result的配置文件内转到jsp页面时用URL传递参数

    Struts.2.5.5版本在Action配置文件中内有如下result,其中role是Action类中的属性,在配置文件中用到OGNL表达式 <result name="input& ...

  7. 实现在当前的日期上加N天

    function getNewDay(dateTemp, days) { var dateTemp = dateTemp.split("-"); var nDate = new D ...

  8. quartz延迟执行一次

    package com.example.balabala; import org.quartz.*; import org.quartz.impl.StdSchedulerFactory; impor ...

  9. matlab学习(2) sort、sortrows

    1.sort函数 对于向量,sort(X)把向量的元素按照从小到大排序: 对于矩阵,sort(X)按照从小到大顺序对矩阵每一列进行排序:sort(X,2)按照行排序 对于字符串的元胞数组,sort(X ...

  10. annotation注释简单介绍

    元数据的作用 如果要对于元数据的作用进行分类,目前还没有明确的定义,不过我们可以根据它所起的作用,大致可分为三类: l         编写文档:通过代码里标识的元数据生成文档. l         ...