State.ResourceInside 中会将下一阶段的状态设置为 State.ResourceOutside,然后开始启动调用 InvokeInnerFilterAsync(),当 ControllerActionInvoker 中的过滤器执行完成之后,再回过头来执行 ResourceOutside 相关内容。
好了,现在流程已经正式来到了 ControllerActionInvoker。
在 ControllerActionInvoker 中,主要处理 3 种类型的过滤器。
实现了 IExceptionFilter 接口或 IAsyncExceptionFilter 接口的过滤器,处理包括发生在 Controller 创建及 模型绑定 期间出现的异常。它们只在管道内发生异常时才会被调用。
实现了 IActionFilter 接口或 IAsyncActionFilter 接口的过滤器,它们可以在 action 方法执行的前后被执行。
实现了 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; }