HTML5技术

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

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

State.ResourceInside 中会将下一阶段的状态设置为 State.ResourceOutside,然后开始启动调用 InvokeInnerFilterAsync(),当 ControllerActionInvoker 中的过滤器执行完成之后,再回过头来执行 ResourceOutside 相

State.ResourceInside 中会将下一阶段的状态设置为 State.ResourceOutside,然后开始启动调用 InvokeInnerFilterAsync(),当 ControllerActionInvoker 中的过滤器执行完成之后,再回过头来执行 ResourceOutside 相关内容。

好了,现在流程已经正式来到了 ControllerActionInvoker。

在 ControllerActionInvoker 中,主要处理 3 种类型的过滤器。

  • Exception Filters
  • 实现了 IExceptionFilter 接口或 IAsyncExceptionFilter 接口的过滤器,处理包括发生在 Controller 创建及 模型绑定 期间出现的异常。它们只在管道内发生异常时才会被调用。

  • Action Filters
  • 实现了 IActionFilter 接口或 IAsyncActionFilter 接口的过滤器,它们可以在 action 方法执行的前后被执行。

  • Result Filters
  • 实现了 IResultFilter 或 IAsyncResultFilter 接口。Result Filter 在 Action Result 执行体的周围执行。当 Action 或 Action 过滤器产生 Action 结果时,只有成功运行的才会执行结果过滤器。如果异常过滤器处理了异常,那么结果过滤器就不会运行——除非异常过滤器将异常设置为null。

    源码流程

    下面是 ControllerActionInvoker 中的 InvokeInnerFilterAsync

    protected override async Task InvokeInnerFilterAsync() { var next = State.ResourceInsideBegin; var scope = Scope.Resource; var state = (object)null; var isCompleted = false; while (!isCompleted) { await Next(ref next, ref scope, ref state, ref isCompleted); } }

    它的起始状态从 State.ResourceInsideBegin 开始,核心方法还是 Next 方法。

    在源代码中,状态的流转是先从 Exception 开始,然后对Exception过滤器进行"压栈",但是并不会执行过滤器中的代码,接着会执行Action相关状态代码,在 State.ActionAsyncBegin 这个状态中会执行 Action Filters 中的 OnActionExecuting,然后在 State.ActionSyncEnd 这个状态中执行OnActionExecuted。

    注意: Action Filter 的执行代码由一个 Try Catch 代码块包装,当发生异常的时候,MVC会把这些信息包装成为一个 ActionExecutedContext 对象,然后会接着执行 Action Filter 里面 OnActionExecuted。

    等 Action Filter 相关的过滤器执行完成之后会将状态置为 State.ExceptionSyncEnd 开始执行 Exception Filter 相关业务。

    在 整个管道的流程中,用户在 Action 中的代码是在 State.ActionInside 这个状态中执行的,它在 Action Filter 的 OnActionExecuting 后执行。

    用户代码Action的调用主要是下面这个函数:

    private async Task InvokeActionMethodAsync() { var controllerContext = _controllerContext; var executor = _executor; var controller = _controller; var arguments = _arguments; //构建Action参数 var orderedArguments = ControllerActionExecutor.PrepareArguments(arguments, executor); IActionResult result = null; var returnType = executor.MethodReturnType; // void 返回结果,执行后返回 EmptyResult if (returnType == typeof(void)) { executor.Execute(controller, orderedArguments); result = new EmptyResult(); } (returnType == typeof(Task)) { await (Task)executor.Execute(controller, orderedArguments); result = new EmptyResult(); } (executor.TaskGenericType == typeof(IActionResult)) { result = await (Task<IActionResult>)executor.Execute(controller, orderedArguments); if (result == null) { ( Resources.FormatActionResult_ActionReturnValueCannotBeNull(typeof(IActionResult))); } } (executor.IsTypeAssignableFromIActionResult) { //是否为异步Action if (_executor.IsMethodAsync) { result = (IActionResult)await _executor.ExecuteAsync(controller, orderedArguments); } else { result = (IActionResult)_executor.Execute(controller, orderedArguments); } if (result == null) { ( Resources.FormatActionResult_ActionReturnValueCannotBeNull(_executor.TaskGenericType ?? returnType)); } } (!executor.IsMethodAsync) { var resultAsObject = executor.Execute(controller, orderedArguments); result = resultAsObject as IActionResult ?? new ObjectResult(resultAsObject) { DeclaredType = returnType, }; } else if (executor.TaskGenericType != null) { var resultAsObject = await executor.ExecuteAsync(controller, orderedArguments); result = resultAsObject as IActionResult ?? new ObjectResult(resultAsObject) { DeclaredType = executor.TaskGenericType, }; } else { (Resources.FormatActionExecutor_UnexpectedTaskInstance( executor.MethodInfo.Name, executor.MethodInfo.DeclaringType)); } _result = result; }

     

    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

    网友点评