protected override async Task <IActionResult> InvokeActionAsync(ActionExecutingContext actionExecutingContext)
        {
            if (actionExecutingContext == null)
            {
                throw new ArgumentNullException(nameof(actionExecutingContext));
            }

            var actionMethodInfo = _descriptor.MethodInfo;

            var methodExecutor = GetControllerActionMethodExecutor();

            var arguments = ControllerActionExecutor.PrepareArguments(
                actionExecutingContext.ActionArguments,
                actionMethodInfo.GetParameters());

            Logger.ActionMethodExecuting(actionExecutingContext, arguments);

            var actionReturnValue = await ControllerActionExecutor.ExecuteAsync(
                methodExecutor,
                actionExecutingContext.Controller,
                arguments);

            var actionResult = CreateActionResult(
                actionMethodInfo.ReturnType,
                actionReturnValue);

            Logger.ActionMethodExecuted(actionExecutingContext, actionResult);

            return(actionResult);
        }
        private async Task <object> ExecuteAction(
            Delegate methodDelegate,
            TestController controller,
            object[] actionParameters)
        {
            var executor = ObjectMethodExecutor.Create(methodDelegate.GetMethodInfo(), _controller.GetType().GetTypeInfo());

            var result = await ControllerActionExecutor.ExecuteAsync(
                executor,
                controller,
                actionParameters);

            return(result);
        }
Beispiel #3
0
        private async Task InvokeActionFilterAsync()
        {
            Debug.Assert(_actionExecutingContext != null);

            var item = _cursor.GetNextFilter <IActionFilter, IAsyncActionFilter>();

            try
            {
                if (item.FilterAsync != null)
                {
                    _diagnosticSource.BeforeOnActionExecution(_actionExecutingContext, item.FilterAsync);

                    await item.FilterAsync.OnActionExecutionAsync(_actionExecutingContext, InvokeActionFilterAwaitedAsync);

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

                        _actionExecutedContext = new ActionExecutedContext(
                            _actionExecutingContext,
                            _filters,
                            _controller)
                        {
                            Canceled = true,
                            Result   = _actionExecutingContext.Result,
                        };
                    }

                    _diagnosticSource.AfterOnActionExecution(_actionExecutedContext, item.FilterAsync);
                }
                else if (item.Filter != null)
                {
                    _diagnosticSource.BeforeOnActionExecuting(_actionExecutingContext, item.Filter);

                    item.Filter.OnActionExecuting(_actionExecutingContext);

                    _diagnosticSource.AfterOnActionExecuting(_actionExecutingContext, item.Filter);

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

                        _actionExecutedContext = new ActionExecutedContext(
                            _actionExecutingContext,
                            _filters,
                            _controller)
                        {
                            Canceled = true,
                            Result   = _actionExecutingContext.Result,
                        };
                    }
                    else
                    {
                        await InvokeActionFilterAsync();

                        Debug.Assert(_actionExecutedContext != null);

                        _diagnosticSource.BeforeOnActionExecuted(_actionExecutedContext, item.Filter);

                        item.Filter.OnActionExecuted(_actionExecutedContext);

                        _diagnosticSource.BeforeOnActionExecuted(_actionExecutedContext, item.Filter);
                    }
                }
                else
                {
                    // All action filters have run, execute the action method.
                    IActionResult result = null;

                    try
                    {
                        _diagnosticSource.BeforeActionMethod(
                            _controllerContext,
                            _actionExecutingContext.ActionArguments,
                            _actionExecutingContext.Controller);

                        var actionMethodInfo = _controllerContext.ActionDescriptor.MethodInfo;

                        var arguments = ControllerActionExecutor.PrepareArguments(
                            _actionExecutingContext.ActionArguments,
                            _executor);

                        _logger.ActionMethodExecuting(_actionExecutingContext, arguments);

                        var returnType = _executor.MethodReturnType;

                        if (returnType == typeof(void))
                        {
                            _executor.Execute(_controller, arguments);
                            result = new EmptyResult();
                        }
                        else if (returnType == typeof(Task))
                        {
                            await(Task) _executor.Execute(_controller, arguments);
                            result = new EmptyResult();
                        }
                        else if (_executor.TaskGenericType == typeof(IActionResult))
                        {
                            result = await(Task <IActionResult>) _executor.Execute(_controller, arguments);
                            if (result == null)
                            {
                                throw new InvalidOperationException(
                                          Resources.FormatActionResult_ActionReturnValueCannotBeNull(typeof(IActionResult)));
                            }
                        }
                        else if (_executor.IsTypeAssignableFromIActionResult)
                        {
                            if (_executor.IsMethodAsync)
                            {
                                result = (IActionResult)await _executor.ExecuteAsync(_controller, arguments);
                            }
                            else
                            {
                                result = (IActionResult)_executor.Execute(_controller, arguments);
                            }

                            if (result == null)
                            {
                                throw new InvalidOperationException(
                                          Resources.FormatActionResult_ActionReturnValueCannotBeNull(_executor.TaskGenericType ?? returnType));
                            }
                        }
                        else if (!_executor.IsMethodAsync)
                        {
                            var resultAsObject = _executor.Execute(_controller, arguments);
                            result = new ObjectResult(resultAsObject)
                            {
                                DeclaredType = returnType,
                            };
                        }
                        else if (_executor.TaskGenericType != null)
                        {
                            var resultAsObject = await _executor.ExecuteAsync(_controller, arguments);

                            result = new ObjectResult(resultAsObject)
                            {
                                DeclaredType = _executor.TaskGenericType,
                            };
                        }
                        else
                        {
                            // This will be the case for types which have derived from Task and Task<T> or non Task types.
                            throw new InvalidOperationException(Resources.FormatActionExecutor_UnexpectedTaskInstance(
                                                                    _executor.MethodInfo.Name,
                                                                    _executor.MethodInfo.DeclaringType));
                        }

                        _logger.ActionMethodExecuted(_actionExecutingContext, result);
                    }
                    finally
                    {
                        _diagnosticSource.AfterActionMethod(
                            _controllerContext,
                            _actionExecutingContext.ActionArguments,
                            _actionExecutingContext.Controller,
                            result);
                    }

                    _actionExecutedContext = new ActionExecutedContext(
                        _actionExecutingContext,
                        _filters,
                        _controller)
                    {
                        Result = result
                    };
                }
            }
            catch (Exception exception)
            {
                // Exceptions thrown by the action method OR filters bubble back up through ActionExcecutedContext.
                _actionExecutedContext = new ActionExecutedContext(
                    _actionExecutingContext,
                    _filters,
                    _controller)
                {
                    ExceptionDispatchInfo = ExceptionDispatchInfo.Capture(exception)
                };
            }

            Debug.Assert(_actionExecutedContext != null);
        }