HTML5技术

ASP.NET Core MVC 源码学习:详解 Action 的激活 - Savorboard

字号+ 作者:H5之家 来源:H5之家 2017-04-14 13:04 我要评论( )

前言 在上一篇文章中,我们已经知道了在 ASP.NET Core MVC 中如何发现一个 Action,那么在发现了Action之后,就是 Action 的一个调用过程,也就是整个 Action 执行的生命周期,那么本文我们就来一起看一下Action是怎么激活并且执行的吧。 Getting Started 还

前言

在上一篇文章中,我们已经知道了在 ASP.NET Core MVC 中如何发现一个 Action,那么在发现了Action之后,就是 Action 的一个调用过程,也就是整个 Action 执行的生命周期,那么本文我们就来一起看一下Action是怎么激活并且执行的吧。

Getting Started

还是从 MvcRouteHandler 的 RouteAsync()开始说起,在上一篇的结尾中,我们已经拿到了 actionDescriptor 这个对象,接着,MVC 会把 actionDescriptor 和 routeData 已经 HttpContext 对象一起包装成为一个 ActionContext 上下文对象。

ActionContext:

public class ActionContext { public ActionDescriptor ActionDescriptor {get; set;} public HttpContext HttpContext {get; set;} public ModelStateDictionary ModelState {get;} public RouteData RouteData {get; set;} }

在有了 ActionContext 之后,接下来就是创建 ControllerActionInvoker 的过程,MVC 会通过一个工厂(ActionInvokerFactory)来创建 Action 对应的 Invoker 对象。

创建 ActionInvoker 的过程如下:

代码如下:

context.Handler = (c) => { var routeData = c.GetRouteData(); var actionContext = new ActionContext(context.HttpContext, routeData, actionDescriptor); var invoker = _actionInvokerFactory.CreateInvoker(actionContext); return invoker.InvokeAsync(); };

开始调用 invoker.InvokerAsync()

InvokerAsync 中的过程其实就是一个管线过滤器执行的过程,在这个管线中,每一步 Action的流转都具有当前管线执行的一个状态,这个过程有点像中间件的执行过程,我们一起来看下。

在 MVC Core 中,过滤器分为 5 大类,分别是:

关于过滤器的管道执行主要包含两个类,分别是 ResourceInvoker 和 ControllerActionInvoker。 其中 ControllerActionInvoker 继承自ResourceInvoker 并且实现了 IActionInvoker 接口。

下面,我们就来看一下 源码 中关于这一部分是如何实现的。

ResourceInvoker

在 ResourceInvoker 中,拥有管线的入口函数,即 InvokeAsync(),在这个函数中又调用了 InvokeFilterPipelineAsync()。

以下这个函数是调用过程的核心函数:

private async Task InvokeFilterPipelineAsync() { var next = State.InvokeBegin; scope = Scope.Invoker; // 'state'用于状态之间的转换期间的内部状态处理。 // 实际上,也就是说将过滤器实例存储在“state”中,然后在下一个状态下检索它。 var state = (object)null; // 当到达终点 state 时, `isCompleted` 会被设置为true var isCompleted = false; while (!isCompleted) { await Next(ref next, ref scope, ref state, ref isCompleted); } }

可以看到,里面有一个Next循环,直到 isCompleted 为 true 时才停止,那么在这个 Next 中会依次执行各个过滤器。

管线针对于MVC预设的几个过滤器他们对应的执行顺序如下图:

在 ResourceInvoker 中,主要处理两种类型的过滤器,他们是 Authorization Filters 和 Resource Filter 。

  • Authorization Filters
  • 在 Next 中,会把处理的每个阶段的状态作为一个枚举类型,然后使用的 Switch Case 手动进行的状态的处理,那么在处理 Authorization 相关的过滤器的时候,其 State 具有以下状态:

    AuthorizationBegin, AuthorizationNext, AuthorizationAsyncBegin, AuthorizationAsyncEnd, AuthorizationSync, AuthorizationShortCircuit, AuthorizationEnd,

    关于每一种状态的处理大家可以直接看这里的
    ,比较简单就不详细说了。

    有一点需要说明的是 在 过滤器的处理中,AuthorizationShortCircuit 这个状态是用来处理短路的情况的,也就是说在过滤器中如果对 Context.Result 赋值了,那么会短路过滤器的管道,直接将 isCompleted 标记为 true,结束管道流程。

    AuthorizationSync 这个状态是执行 OnAuthorization 的关键流程,IAuthorizationFilter 的实现将在这个流程中执行。

  • Resource Filters
  • Resource Filter 是 ASP.NET Core MVC 中新增加的一个过滤器,它在管道中的调用顺序仅次于Authorization,在其后执行。用户可以实现 IResourceFilter 或 IAsyncExceptionFilter 接口来自定义 Resource 过滤器, 它主要是此过滤器来实现一些需要短路过滤器管线的一些操作。比如说:缓存(如果被命中,则直接返回,短路管线)。

    下面是 Resource 中涉及的所有状态。

    ResourceBegin, ResourceNext, ResourceAsyncBegin, ResourceAsyncEnd, ResourceSyncBegin, ResourceSyncEnd, ResourceShortCircuit, ResourceInside, ResourceOutside, ResourceEnd

    ControllerActionInvoker

    ControllerActionInvoker 重写了 ResourceInvoker 中的InvokeInnerFilterAsync()方法,然后经由 ControllerActionInvokerProvider 实例化。

    既然流程是从 ResourceInvoker 开始的,那么我们看一下在 ResourceInvoker 中哪一步调用了 InvokeInnerFilterAsync()。

    在 ResourceInvoker 中主要有两个状态来调用它,一个是 State.ResourceNext,另外一个是 State.ResourceInside。

    State.ResourceNext 中如果没有检测到有 Resource Filter 这直接开始下一阶段的 Filter调用,即 ControllerActionInvoker 中处理的过滤器。

     

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章
    • ASP.NET Core 网站在Docker中运行 - 漫步长江

      ASP.NET Core 网站在Docker中运行 - 漫步长江

      2017-04-13 12:00

    • .NetCore上传多文件的几种示例 - 神牛步行3

      .NetCore上传多文件的几种示例 - 神牛步行3

      2017-04-11 18:00

    • 云计算之路-阿里云上:数据库连接数过万的真相,从阿里云RDS到微软.NET Core - 博客园团队

      云计算之路-阿里云上:数据库连接数过万的真相,从阿里云RDS到微软.N

      2017-04-08 15:00

    • VS 2017开发ASP.NET Core Web应用过程中发现的一个重大Bug - 雲霏霏

      VS 2017开发ASP.NET Core Web应用过程中发现的一个重大Bug - 雲霏霏

      2017-04-07 16:01

    网友点评
    5