Пример #1
0
        private Task InvokeNextActionFilterAsync()
        {
            try
            {
                var next        = State.ActionNext;
                var state       = (object)null;
                var scope       = Scope.Action;
                var isCompleted = false;
                while (!isCompleted)
                {
                    var lastTask = Next(ref next, ref scope, ref state, ref isCompleted);
                    if (!lastTask.IsCompletedSuccessfully)
                    {
                        return(Awaited(this, lastTask, next, scope, state, isCompleted));
                    }
                }
            }
            catch (Exception exception)
            {
                _actionExecutedContext = new ActionExecutedContextSealed(_controllerContext, _filters, _instance)
                {
                    ExceptionDispatchInfo = ExceptionDispatchInfo.Capture(exception),
                };
            }

            Debug.Assert(_actionExecutedContext != null);
            return(Task.CompletedTask);
Пример #2
0
        private Task Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
        {
            switch (next)
            {
            case State.ActionBegin:
            {
                var controllerContext = _controllerContext;

                _cursor.Reset();

                _logger.ExecutingControllerFactory(controllerContext);

                _instance = _cacheEntry.ControllerFactory(controllerContext);

                _logger.ExecutedControllerFactory(controllerContext);

                _arguments = new Dictionary <string, object>(StringComparer.OrdinalIgnoreCase);

                var task = BindArgumentsAsync();
                if (task.Status != TaskStatus.RanToCompletion)
                {
                    next = State.ActionNext;
                    return(task);
                }

                goto case State.ActionNext;
            }

            case State.ActionNext:
            {
                var current = _cursor.GetNextFilter <IActionFilter, IAsyncActionFilter>();
                if (current.FilterAsync != null)
                {
                    if (_actionExecutingContext == null)
                    {
                        _actionExecutingContext = new ActionExecutingContextSealed(_controllerContext, _filters, _arguments, _instance);
                    }

                    state = current.FilterAsync;
                    goto case State.ActionAsyncBegin;
                }
                else if (current.Filter != null)
                {
                    if (_actionExecutingContext == null)
                    {
                        _actionExecutingContext = new ActionExecutingContextSealed(_controllerContext, _filters, _arguments, _instance);
                    }

                    state = current.Filter;
                    goto case State.ActionSyncBegin;
                }
                else
                {
                    goto case State.ActionInside;
                }
            }

            case State.ActionAsyncBegin:
            {
                Debug.Assert(state != null);
                Debug.Assert(_actionExecutingContext != null);

                var filter = (IAsyncActionFilter)state;
                var actionExecutingContext = _actionExecutingContext;

                _diagnosticListener.BeforeOnActionExecution(actionExecutingContext, filter);
                _logger.BeforeExecutingMethodOnFilter(
                    MvcCoreLoggerExtensions.ActionFilter,
                    nameof(IAsyncActionFilter.OnActionExecutionAsync),
                    filter);

                var task = filter.OnActionExecutionAsync(actionExecutingContext, InvokeNextActionFilterAwaitedAsync);
                if (task.Status != TaskStatus.RanToCompletion)
                {
                    next = State.ActionAsyncEnd;
                    return(task);
                }

                goto case State.ActionAsyncEnd;
            }

            case State.ActionAsyncEnd:
            {
                Debug.Assert(state != null);
                Debug.Assert(_actionExecutingContext != null);

                var filter = (IAsyncActionFilter)state;

                if (_actionExecutedContext == null)
                {
                    // If we get here then the filter didn't call 'next' indicating a short circuit.
                    _logger.ActionFilterShortCircuited(filter);

                    _actionExecutedContext = new ActionExecutedContextSealed(
                        _controllerContext,
                        _filters,
                        _instance)
                    {
                        Canceled = true,
                        Result   = _actionExecutingContext.Result,
                    };
                }

                _diagnosticListener.AfterOnActionExecution(_actionExecutedContext, filter);
                _logger.AfterExecutingMethodOnFilter(
                    MvcCoreLoggerExtensions.ActionFilter,
                    nameof(IAsyncActionFilter.OnActionExecutionAsync),
                    filter);

                goto case State.ActionEnd;
            }

            case State.ActionSyncBegin:
            {
                Debug.Assert(state != null);
                Debug.Assert(_actionExecutingContext != null);

                var filter = (IActionFilter)state;
                var actionExecutingContext = _actionExecutingContext;

                _diagnosticListener.BeforeOnActionExecuting(actionExecutingContext, filter);
                _logger.BeforeExecutingMethodOnFilter(
                    MvcCoreLoggerExtensions.ActionFilter,
                    nameof(IActionFilter.OnActionExecuting),
                    filter);

                filter.OnActionExecuting(actionExecutingContext);

                _diagnosticListener.AfterOnActionExecuting(actionExecutingContext, filter);
                _logger.AfterExecutingMethodOnFilter(
                    MvcCoreLoggerExtensions.ActionFilter,
                    nameof(IActionFilter.OnActionExecuting),
                    filter);

                if (actionExecutingContext.Result != null)
                {
                    // Short-circuited by setting a result.
                    _logger.ActionFilterShortCircuited(filter);

                    _actionExecutedContext = new ActionExecutedContextSealed(
                        _actionExecutingContext,
                        _filters,
                        _instance)
                    {
                        Canceled = true,
                        Result   = _actionExecutingContext.Result,
                    };

                    goto case State.ActionEnd;
                }

                var task = InvokeNextActionFilterAsync();
                if (task.Status != TaskStatus.RanToCompletion)
                {
                    next = State.ActionSyncEnd;
                    return(task);
                }

                goto case State.ActionSyncEnd;
            }

            case State.ActionSyncEnd:
            {
                Debug.Assert(state != null);
                Debug.Assert(_actionExecutingContext != null);
                Debug.Assert(_actionExecutedContext != null);

                var filter = (IActionFilter)state;
                var actionExecutedContext = _actionExecutedContext;

                _diagnosticListener.BeforeOnActionExecuted(actionExecutedContext, filter);
                _logger.BeforeExecutingMethodOnFilter(
                    MvcCoreLoggerExtensions.ActionFilter,
                    nameof(IActionFilter.OnActionExecuted),
                    filter);

                filter.OnActionExecuted(actionExecutedContext);

                _diagnosticListener.AfterOnActionExecuted(actionExecutedContext, filter);
                _logger.AfterExecutingMethodOnFilter(
                    MvcCoreLoggerExtensions.ActionFilter,
                    nameof(IActionFilter.OnActionExecuted),
                    filter);

                goto case State.ActionEnd;
            }

            case State.ActionInside:
            {
                var task = InvokeActionMethodAsync();
                if (task.Status != TaskStatus.RanToCompletion)
                {
                    next = State.ActionEnd;
                    return(task);
                }

                goto case State.ActionEnd;
            }

            case State.ActionEnd:
            {
                if (scope == Scope.Action)
                {
                    if (_actionExecutedContext == null)
                    {
                        _actionExecutedContext = new ActionExecutedContextSealed(_controllerContext, _filters, _instance)
                        {
                            Result = _result,
                        };
                    }

                    isCompleted = true;
                    return(Task.CompletedTask);
                }

                var actionExecutedContext = _actionExecutedContext;
                Rethrow(actionExecutedContext);

                if (actionExecutedContext != null)
                {
                    _result = actionExecutedContext.Result;
                }

                isCompleted = true;
                return(Task.CompletedTask);
            }

            default:
                throw new InvalidOperationException();
            }
        }