• 深入理解ASP.NET MVC(7)


    系列目录

    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

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

    image

    image

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

    image

    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中与这四个接口相关的特性如下:

    image

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

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

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

  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    分布式架构在农业银行的应用实践与展望
  • 原文地址:https://www.cnblogs.com/feng-NET/p/4665298.html
Copyright © 2020-2023  润新知