예제 #1
0
        public void Select_ReturnsOnlyHandler()
        {
            // Arrange
            var descriptor = new HandlerMethodDescriptor
            {
                HttpMethod = "GET"
            };

            var pageContext = new PageContext
            {
                ActionDescriptor = new CompiledPageActionDescriptor
                {
                    HandlerMethods = new List <HandlerMethodDescriptor>()
                    {
                        descriptor,
                    },
                },
                RouteData   = new RouteData(),
                HttpContext = new DefaultHttpContext
                {
                    Request =
                    {
                        Method = "GET"
                    },
                },
            };
            var selector = CreateSelector();

            // Act
            var actual = selector.Select(pageContext);

            // Assert
            Assert.Same(descriptor, actual);
        }
예제 #2
0
        private static object[] PrepareArguments(
            IDictionary<string, object> argumentsInDictionary,
            HandlerMethodDescriptor handler)
        {
            if (handler.Parameters.Count == 0)
            {
                return null;
            }

            var arguments = new object[handler.Parameters.Count];
            for (var i = 0; i < arguments.Length; i++)
            {
                var parameter = handler.Parameters[i];

                if (argumentsInDictionary.TryGetValue(parameter.ParameterInfo.Name, out var value))
                {
                    // Do nothing, already set the value.
                }
                else if (!ParameterDefaultValue.TryGetDefaultValue(parameter.ParameterInfo, out value) &&
                    parameter.ParameterInfo.ParameterType.IsValueType)
                {
                    value = Activator.CreateInstance(parameter.ParameterInfo.ParameterType);
                }

                arguments[i] = value;
            }

            return arguments;
        }
예제 #3
0
        private static HandlerMethod CreateHandlerMethod(HandlerMethodDescriptor handlerDescriptor)
        {
            var method     = handlerDescriptor.MethodInfo;
            var parameters = handlerDescriptor.Parameters.ToArray();

            var returnType = method.ReturnType;

            if (returnType == typeof(void))
            {
                return(new VoidHandlerMethod(parameters, method));
            }
            else if (typeof(IActionResult).IsAssignableFrom(returnType))
            {
                return(new ActionResultHandlerMethod(parameters, method));
            }
            else if (returnType == typeof(Task))
            {
                return(new NonGenericTaskHandlerMethod(parameters, method));
            }
            else
            {
                var taskType = ClosedGenericMatcher.ExtractGenericInterface(returnType, typeof(Task <>));
                if (taskType != null && typeof(IActionResult).IsAssignableFrom(taskType.GenericTypeArguments[0]))
                {
                    return(new GenericTaskHandlerMethod(parameters, method));
                }
            }

            throw new InvalidOperationException(Resources.FormatUnsupportedHandlerMethodType(returnType));
        }
            public static HandlerMethodAndMetadata Create(HandlerMethodDescriptor handler)
            {
                var name = handler.Method.Name;

                string httpMethod;

                if (name.StartsWith("OnGet", StringComparison.Ordinal))
                {
                    httpMethod = "GET";
                }
                else if (name.StartsWith("OnPost", StringComparison.Ordinal))
                {
                    httpMethod = "POST";
                }
                else
                {
                    httpMethod = null;
                }

                var formactionStart  = httpMethod?.Length + 2 ?? 0;
                var formactionLength = name.EndsWith("Async", StringComparison.Ordinal)
                    ? name.Length - formactionStart - "Async".Length
                    : name.Length - formactionStart;

                var formaction = formactionLength == 0 ? null : name.Substring(formactionStart, formactionLength);

                return(new HandlerMethodAndMetadata(handler, httpMethod, formaction));
            }
예제 #5
0
        private static PageHandlerExecutingContext GetContext(HandlerMethodDescriptor handlerMethodDescriptor)
        {
            var actionContext = new ActionContext(new DefaultHttpContext(), new RouteData(), new PageActionDescriptor());
            var pageContext   = new PageContext(actionContext);

            return(new PageHandlerExecutingContext(pageContext, Array.Empty <IFilterMetadata>(), handlerMethodDescriptor, new Dictionary <string, object>(), new object()));
        }
예제 #6
0
        public void Select_WithHandler_ThrowsIfMoreThanOneHandlerMatches()
        {
            // Arrange
            var descriptor1 = new HandlerMethodDescriptor
            {
                MethodInfo = GetType().GetMethod(nameof(Post)),
                HttpMethod = "POST",
                Name       = "Add",
            };

            var descriptor2 = new HandlerMethodDescriptor
            {
                MethodInfo = GetType().GetMethod(nameof(PostAsync)),
                HttpMethod = "POST",
                Name       = "Add",
            };

            var descriptor3 = new HandlerMethodDescriptor
            {
                HttpMethod = "GET",
            };

            var pageContext = new PageContext
            {
                ActionDescriptor = new CompiledPageActionDescriptor
                {
                    HandlerMethods = new List <HandlerMethodDescriptor>()
                    {
                        descriptor1,
                        descriptor2,
                        descriptor3,
                    },
                },
                RouteData = new RouteData
                {
                    Values =
                    {
                        { "handler", "Add" }
                    }
                },
                HttpContext = new DefaultHttpContext
                {
                    Request =
                    {
                        Method = "Post"
                    },
                },
            };
            var selector = CreateSelector();

            // Act & Assert
            var ex      = Assert.Throws <InvalidOperationException>(() => selector.Select(pageContext));
            var methods = descriptor1.MethodInfo + ", " + descriptor2.MethodInfo;
            var message = "Multiple handlers matched. The following handlers matched route data and had all constraints satisfied:" +
                          Environment.NewLine + Environment.NewLine + methods;

            Assert.Equal(message, ex.Message);
        }
예제 #7
0
        public static PageHandlerExecutorDelegate CreateExecutor(HandlerMethodDescriptor handlerDescriptor)
        {
            if (handlerDescriptor == null)
            {
                throw new ArgumentNullException(nameof(handlerDescriptor));
            }

            var handler = CreateHandlerMethod(handlerDescriptor);

            return(handler.Execute);
        }
        public HandlerMethodDescriptor Select(PageContext context)
        {
            var handlers = SelectHandlers(context);

            if (handlers == null || handlers.Count == 0)
            {
                return(null);
            }

            List <HandlerMethodDescriptor> ambiguousMatches = null;
            HandlerMethodDescriptor        bestMatch        = null;

            for (var score = 2; score >= 0; score--)
            {
                for (var i = 0; i < handlers.Count; i++)
                {
                    var handler = handlers[i];
                    if (GetScore(handler) == score)
                    {
                        if (bestMatch == null)
                        {
                            bestMatch = handler;
                            continue;
                        }

                        if (ambiguousMatches == null)
                        {
                            ambiguousMatches = new List <HandlerMethodDescriptor>
                            {
                                bestMatch
                            };
                        }

                        ambiguousMatches.Add(handler);
                    }
                }

                if (ambiguousMatches != null)
                {
                    var ambiguousMethods = string.Join(", ", ambiguousMatches.Select(m => m.MethodInfo));
                    throw new InvalidOperationException(Resources.FormatAmbiguousHandler(Environment.NewLine, ambiguousMethods));
                }

                if (bestMatch != null)
                {
                    return(bestMatch);
                }
            }

            return(null);
        }
예제 #9
0
        public void Select_HandlerConsidersRouteDataFirst()
        {
            // Arrange
            var descriptor1 = new HandlerMethodDescriptor
            {
                HttpMethod = "POST",
                Name       = "Add",
            };

            var descriptor2 = new HandlerMethodDescriptor
            {
                HttpMethod = "POST",
                Name       = "Delete",
            };

            var pageContext = new PageContext
            {
                ActionDescriptor = new CompiledPageActionDescriptor
                {
                    HandlerMethods = new List <HandlerMethodDescriptor>()
                    {
                        descriptor1,
                        descriptor2,
                    },
                },
                RouteData = new RouteData
                {
                    Values =
                    {
                        { "handler", "Add" }
                    }
                },
                HttpContext = new DefaultHttpContext
                {
                    Request =
                    {
                        Method      = "Post",
                        QueryString = new QueryString("?handler=Delete"),
                    },
                },
            };
            var selector = CreateSelector();

            // Act
            var actual = selector.Select(pageContext);

            // Assert
            Assert.Same(descriptor1, actual);
        }
예제 #10
0
        public void NewBehavior_Select_PrefersExactMatch_ReturnsNullWhenHandlerNameDoesntMatch()
        {
            // Arrange
            var descriptor1 = new HandlerMethodDescriptor
            {
                HttpMethod = "GET"
            };

            var descriptor2 = new HandlerMethodDescriptor
            {
                HttpMethod = "POST"
            };

            // This will match the HTTP method 'round' of selection, but won't match the
            // handler name.
            var descriptor3 = new HandlerMethodDescriptor
            {
                HttpMethod = "HEAD",
                Name       = "not-provided",
            };

            var pageContext = new PageContext
            {
                ActionDescriptor = new CompiledPageActionDescriptor
                {
                    HandlerMethods = new List <HandlerMethodDescriptor>()
                    {
                        descriptor1,
                        descriptor2,
                        descriptor3,
                    },
                },
                RouteData   = new RouteData(),
                HttpContext = new DefaultHttpContext
                {
                    Request =
                    {
                        Method = "HEAD",
                    },
                },
            };
            var selector = CreateSelector();

            // Act
            var actual = selector.Select(pageContext);

            // Assert
            Assert.Null(actual);
        }
 private static int GetScore(HandlerMethodDescriptor descriptor)
 {
     if (descriptor.Name != null)
     {
         return(2);
     }
     else if (descriptor.HttpMethod != null)
     {
         return(1);
     }
     else
     {
         return(0);
     }
 }
예제 #12
0
        public void CreateExecutor_ThrowsIfTypeIsNotAValidReturnType(string methodName)
        {
            // Arrange
            var methodInfo = typeof(TestPageModel).GetMethod(methodName);
            var handler    = new HandlerMethodDescriptor()
            {
                MethodInfo = methodInfo,
                Parameters = CreateParameters(methodInfo),
            };

            // Act & Assert
            var ex = Assert.Throws <InvalidOperationException>(() => ExecutorFactory.CreateExecutor(handler));

            Assert.Equal($"Unsupported handler method return type '{methodInfo.ReturnType}'.", ex.Message);
        }
예제 #13
0
        public void Select_ReturnsHandlerThatMatchesHandler()
        {
            // Arrange
            var descriptor1 = new HandlerMethodDescriptor
            {
                HttpMethod = "POST",
                Name       = "Add",
            };

            var descriptor2 = new HandlerMethodDescriptor
            {
                HttpMethod = "POST",
                Name       = "Delete",
            };

            var pageContext = new PageContext
            {
                ActionDescriptor = new CompiledPageActionDescriptor
                {
                    HandlerMethods = new List <HandlerMethodDescriptor>()
                    {
                        descriptor1,
                        descriptor2,
                    },
                },
                RouteData = new RouteData
                {
                    Values =
                    {
                        { "handler", "Add" }
                    }
                },
                HttpContext = new DefaultHttpContext
                {
                    Request =
                    {
                        Method = "Post"
                    },
                },
            };
            var selector = CreateSelector();

            // Act
            var actual = selector.Select(pageContext);

            // Assert
            Assert.Same(descriptor1, actual);
        }
예제 #14
0
        public void Select_ReturnsHandlerThatMatchesHandler_UsesInvariantCulture()
        {
            // Arrange
            var descriptor1 = new HandlerMethodDescriptor
            {
                HttpMethod = "POST",
                Name       = "10/31/2018 07:37:38 -07:00",
            };

            var descriptor2 = new HandlerMethodDescriptor
            {
                HttpMethod = "POST",
                Name       = "Delete",
            };

            var pageContext = new PageContext
            {
                ActionDescriptor = new CompiledPageActionDescriptor
                {
                    HandlerMethods = new List <HandlerMethodDescriptor>()
                    {
                        descriptor1,
                        descriptor2,
                    },
                },
                RouteData = new RouteData
                {
                    Values =
                    {
                        { "handler", new DateTimeOffset(2018, 10, 31, 7, 37, 38, TimeSpan.FromHours(-7)) },
                    }
                },
                HttpContext = new DefaultHttpContext
                {
                    Request =
                    {
                        Method = "Post"
                    },
                },
            };
            var selector = CreateSelector();

            // Act
            var actual = selector.Select(pageContext);

            // Assert
            Assert.Same(descriptor1, actual);
        }
예제 #15
0
        public void NewBehavior_Select_PrefersExactMatch()
        {
            // Arrange
            var descriptor1 = new HandlerMethodDescriptor
            {
                HttpMethod = "GET"
            };

            var descriptor2 = new HandlerMethodDescriptor
            {
                HttpMethod = "POST"
            };

            var descriptor3 = new HandlerMethodDescriptor
            {
                HttpMethod = "HEAD"
            };

            var pageContext = new PageContext
            {
                ActionDescriptor = new CompiledPageActionDescriptor
                {
                    HandlerMethods = new List <HandlerMethodDescriptor>()
                    {
                        descriptor1,
                        descriptor2,
                        descriptor3,
                    },
                },
                RouteData   = new RouteData(),
                HttpContext = new DefaultHttpContext
                {
                    Request =
                    {
                        Method = "HEAD",
                    },
                },
            };
            var selector = CreateSelector();

            // Act
            var actual = selector.Select(pageContext);

            // Assert
            Assert.Same(descriptor3, actual);
        }
예제 #16
0
        public async Task CreateExecutor_ForMethodReturningConcreteSubtypeOfIActionResult()
        {
            // Arrange
            var handler = new HandlerMethodDescriptor()
            {
                MethodInfo = typeof(TestPage).GetMethod(nameof(TestPage.ConcreteActionResult)),
                Parameters = new HandlerParameterDescriptor[0],
            };

            // Act
            var executor = ExecutorFactory.CreateExecutor(handler);

            // Assert
            Assert.NotNull(executor);
            var actionResultTask = executor(new TestPage(), null);
            var actionResult     = await actionResultTask;

            Assert.IsType <ViewResult>(actionResult);
        }
예제 #17
0
        public async Task CreateExecutor_ForTaskOfIActionResultReturningMethod()
        {
            // Arrange
            var methodInfo = typeof(TestPage).GetMethod(nameof(TestPage.GenericTaskHandler));
            var handler    = new HandlerMethodDescriptor()
            {
                MethodInfo = methodInfo,
                Parameters = CreateParameters(methodInfo),
            };

            // Act
            var executor = ExecutorFactory.CreateExecutor(handler);

            // Assert
            Assert.NotNull(executor);
            var actionResultTask = executor(new TestPage(), null);
            var actionResult     = await actionResultTask;

            Assert.IsType <EmptyResult>(actionResult);
        }
예제 #18
0
        public async Task CreateExecutor_ForActionResultReturningMethod_WithParameters()
        {
            // Arrange
            var methodInfo = typeof(TestPage).GetMethod(nameof(TestPage.ActionResultReturnHandlerWithParameters));
            var handler    = new HandlerMethodDescriptor()
            {
                MethodInfo = methodInfo,
                Parameters = CreateParameters(methodInfo),
            };

            // Act
            var executor = ExecutorFactory.CreateExecutor(handler);

            // Assert
            Assert.NotNull(executor);
            var actionResultTask = executor(new TestPage(), CreateArguments(methodInfo));
            var actionResult     = await actionResultTask;
            var contentResult    = Assert.IsType <ContentResult>(actionResult);

            Assert.Equal("Hello 0", contentResult.Content);
        }
예제 #19
0
        public void LegacyBehavior_Select_ReturnsNull_WhenNoHandlerMatchesHttpMethod()
        {
            // Arrange
            var descriptor1 = new HandlerMethodDescriptor
            {
                HttpMethod = "GET"
            };

            var descriptor2 = new HandlerMethodDescriptor
            {
                HttpMethod = "POST"
            };

            var pageContext = new PageContext
            {
                ActionDescriptor = new CompiledPageActionDescriptor
                {
                    HandlerMethods = new List <HandlerMethodDescriptor>()
                    {
                        descriptor1,
                        descriptor2,
                    },
                },
                RouteData   = new RouteData(),
                HttpContext = new DefaultHttpContext
                {
                    Request =
                    {
                        Method = "PUT"
                    },
                },
            };
            var selector = CreateSelector(legacyBehavior: true);

            // Act
            var actual = selector.Select(pageContext);

            // Assert
            Assert.Null(actual);
        }
예제 #20
0
        public void NewBehavior_Select_ReturnsFuzzyMatch_SafeVerbs(string httpMethod)
        {
            // Arrange
            var descriptor1 = new HandlerMethodDescriptor
            {
                HttpMethod = "GET"
            };

            var descriptor2 = new HandlerMethodDescriptor
            {
                HttpMethod = "POST"
            };

            var pageContext = new PageContext
            {
                ActionDescriptor = new CompiledPageActionDescriptor
                {
                    HandlerMethods = new List <HandlerMethodDescriptor>()
                    {
                        descriptor1,
                        descriptor2,
                    },
                },
                RouteData   = new RouteData(),
                HttpContext = new DefaultHttpContext
                {
                    Request =
                    {
                        Method = httpMethod
                    },
                },
            };
            var selector = CreateSelector();

            // Act
            var actual = selector.Select(pageContext);

            // Assert
            Assert.Same(descriptor1, actual);
        }
예제 #21
0
        public async Task CreateExecutor_ForVoidReturningMethod()
        {
            // Arrange
            var handler = new HandlerMethodDescriptor()
            {
                MethodInfo = typeof(TestPage).GetMethod(nameof(TestPage.VoidReturningHandler)),
                Parameters = new HandlerParameterDescriptor[0],
            };

            var page = new TestPage();

            // Act
            var executor = ExecutorFactory.CreateExecutor(handler);

            // Assert
            Assert.NotNull(executor);
            var actionResultTask = executor(page, null);
            var actionResult     = await actionResultTask;

            Assert.Null(actionResult);
            Assert.True(page.SideEffects);
        }
예제 #22
0
        public void Select_ReturnsHandlerWithMatchingHttpRequestMethod(string httpMethod)
        {
            // Arrange
            var descriptor1 = new HandlerMethodDescriptor
            {
                HttpMethod = "PUT",
            };
            var descriptor2 = new HandlerMethodDescriptor
            {
                HttpMethod = httpMethod,
            };

            var pageContext = new PageContext
            {
                ActionDescriptor = new CompiledPageActionDescriptor
                {
                    HandlerMethods = new List <HandlerMethodDescriptor>()
                    {
                        descriptor1,
                        descriptor2,
                    },
                },
                RouteData   = new RouteData(),
                HttpContext = new DefaultHttpContext
                {
                    Request =
                    {
                        Method = httpMethod,
                    },
                },
            };
            var selector = CreateSelector();

            // Act
            var actual = selector.Select(pageContext);

            // Assert
            Assert.Same(descriptor2, actual);
        }
 public HandlerMethodAndMetadata(HandlerMethodDescriptor handler, string httpMethod, string formaction)
 {
     Handler    = handler;
     HttpMethod = httpMethod;
     Formaction = formaction;
 }
예제 #24
0
        private Task Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
        {
            switch (next)
            {
                case State.PageBegin:
                    {
                        _instance = CreateInstance();

                        goto case State.PageSelectHandlerBegin;
                    }

                case State.PageSelectHandlerBegin:
                    {
                        _cursor.Reset();

                        _handler = SelectHandler();

                        goto case State.PageSelectHandlerNext;
                    }

                case State.PageSelectHandlerNext:

                    var currentSelector = _cursor.GetNextFilter<IPageFilter, IAsyncPageFilter>();
                    if (currentSelector.FilterAsync != null)
                    {
                        if (_handlerSelectedContext == null)
                        {
                            _handlerSelectedContext = new PageHandlerSelectedContext(_pageContext, _filters, _instance)
                            {
                                HandlerMethod = _handler,
                            };
                        }

                        state = currentSelector.FilterAsync;
                        goto case State.PageSelectHandlerAsyncBegin;
                    }
                    else if (currentSelector.Filter != null)
                    {
                        if (_handlerSelectedContext == null)
                        {
                            _handlerSelectedContext = new PageHandlerSelectedContext(_pageContext, _filters, _instance)
                            {
                                HandlerMethod = _handler,
                            };
                        }

                        state = currentSelector.Filter;
                        goto case State.PageSelectHandlerSync;
                    }
                    else
                    {
                        goto case State.PageSelectHandlerEnd;
                    }

                case State.PageSelectHandlerAsyncBegin:
                    {
                        Debug.Assert(state != null);
                        Debug.Assert(_handlerSelectedContext != null);

                        var filter = (IAsyncPageFilter)state;
                        var handlerSelectedContext = _handlerSelectedContext;

                        _diagnosticListener.BeforeOnPageHandlerSelection(handlerSelectedContext, filter);
                        _logger.BeforeExecutingMethodOnFilter(
                            PageLoggerExtensions.PageFilter,
                            nameof(IAsyncPageFilter.OnPageHandlerSelectionAsync),
                            filter);

                        var task = filter.OnPageHandlerSelectionAsync(handlerSelectedContext);
                        if (task.Status != TaskStatus.RanToCompletion)
                        {
                            next = State.PageSelectHandlerAsyncEnd;
                            return task;
                        }

                        goto case State.PageSelectHandlerAsyncEnd;
                    }

                case State.PageSelectHandlerAsyncEnd:
                    {
                        Debug.Assert(state != null);
                        Debug.Assert(_handlerSelectedContext != null);

                        var filter = (IAsyncPageFilter)state;

                        _diagnosticListener.AfterOnPageHandlerSelection(_handlerSelectedContext, filter);
                        _logger.AfterExecutingMethodOnFilter(
                            PageLoggerExtensions.PageFilter,
                            nameof(IAsyncPageFilter.OnPageHandlerSelectionAsync),
                            filter);

                        goto case State.PageSelectHandlerNext;
                    }

                case State.PageSelectHandlerSync:
                    {
                        Debug.Assert(state != null);
                        Debug.Assert(_handlerSelectedContext != null);

                        var filter = (IPageFilter)state;
                        var handlerSelectedContext = _handlerSelectedContext;

                        _diagnosticListener.BeforeOnPageHandlerSelected(handlerSelectedContext, filter);
                        _logger.BeforeExecutingMethodOnFilter(
                            PageLoggerExtensions.PageFilter,
                            nameof(IPageFilter.OnPageHandlerSelected),
                            filter);

                        filter.OnPageHandlerSelected(handlerSelectedContext);

                        _diagnosticListener.AfterOnPageHandlerSelected(handlerSelectedContext, filter);

                        goto case State.PageSelectHandlerNext;
                    }

                case State.PageSelectHandlerEnd:
                    {
                        if (_handlerSelectedContext != null)
                        {
                            _handler = _handlerSelectedContext.HandlerMethod;
                        }

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

                        _cursor.Reset();

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

                        goto case State.PageNext;
                    }

                case State.PageNext:
                    {
                        var current = _cursor.GetNextFilter<IPageFilter, IAsyncPageFilter>();
                        if (current.FilterAsync != null)
                        {
                            if (_handlerExecutingContext == null)
                            {
                                _handlerExecutingContext = new PageHandlerExecutingContext(_pageContext, _filters, _handler, _arguments, _instance);
                            }

                            state = current.FilterAsync;
                            goto case State.PageAsyncBegin;
                        }
                        else if (current.Filter != null)
                        {
                            if (_handlerExecutingContext == null)
                            {
                                _handlerExecutingContext = new PageHandlerExecutingContext(_pageContext, _filters, _handler, _arguments, _instance);
                            }

                            state = current.Filter;
                            goto case State.PageSyncBegin;
                        }
                        else
                        {
                            goto case State.PageInside;
                        }
                    }

                case State.PageAsyncBegin:
                    {
                        Debug.Assert(state != null);
                        Debug.Assert(_handlerExecutingContext != null);

                        var filter = (IAsyncPageFilter)state;
                        var handlerExecutingContext = _handlerExecutingContext;

                        _diagnosticListener.BeforeOnPageHandlerExecution(handlerExecutingContext, filter);
                        _logger.BeforeExecutingMethodOnFilter(
                            PageLoggerExtensions.PageFilter,
                            nameof(IAsyncPageFilter.OnPageHandlerExecutionAsync),
                            filter);

                        var task = filter.OnPageHandlerExecutionAsync(handlerExecutingContext, InvokeNextPageFilterAwaitedAsync);
                        if (task.Status != TaskStatus.RanToCompletion)
                        {
                            next = State.PageAsyncEnd;
                            return task;
                        }

                        goto case State.PageAsyncEnd;
                    }

                case State.PageAsyncEnd:
                    {
                        Debug.Assert(state != null);
                        Debug.Assert(_handlerExecutingContext != null);

                        var filter = (IAsyncPageFilter)state;

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

                            _handlerExecutedContext = new PageHandlerExecutedContext(
                                _pageContext,
                                _filters,
                                _handler,
                                _instance)
                            {
                                Canceled = true,
                                Result = _handlerExecutingContext.Result,
                            };
                        }

                        _diagnosticListener.AfterOnPageHandlerExecution(_handlerExecutedContext, filter);
                        _logger.AfterExecutingMethodOnFilter(
                           PageLoggerExtensions.PageFilter,
                           nameof(IAsyncPageFilter.OnPageHandlerExecutionAsync),
                           filter);

                        goto case State.PageEnd;
                    }

                case State.PageSyncBegin:
                    {
                        Debug.Assert(state != null);
                        Debug.Assert(_handlerExecutingContext != null);

                        var filter = (IPageFilter)state;
                        var handlerExecutingContext = _handlerExecutingContext;

                        _diagnosticListener.BeforeOnPageHandlerExecuting(handlerExecutingContext, filter);
                        _logger.BeforeExecutingMethodOnFilter(
                           PageLoggerExtensions.PageFilter,
                           nameof(IPageFilter.OnPageHandlerExecuting),
                           filter);

                        filter.OnPageHandlerExecuting(handlerExecutingContext);

                        _diagnosticListener.AfterOnPageHandlerExecuting(handlerExecutingContext, filter);
                        _logger.AfterExecutingMethodOnFilter(
                           PageLoggerExtensions.PageFilter,
                           nameof(IPageFilter.OnPageHandlerExecuting),
                           filter);

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

                            _handlerExecutedContext = new PageHandlerExecutedContext(
                                _pageContext,
                                _filters,
                                _handler,
                                _instance)
                            {
                                Canceled = true,
                                Result = _handlerExecutingContext.Result,
                            };

                            goto case State.PageEnd;
                        }

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

                        goto case State.PageSyncEnd;
                    }

                case State.PageSyncEnd:
                    {
                        Debug.Assert(state != null);
                        Debug.Assert(_handlerExecutingContext != null);
                        Debug.Assert(_handlerExecutedContext != null);

                        var filter = (IPageFilter)state;
                        var handlerExecutedContext = _handlerExecutedContext;

                        _diagnosticListener.BeforeOnPageHandlerExecuted(handlerExecutedContext, filter);
                        _logger.BeforeExecutingMethodOnFilter(
                           PageLoggerExtensions.PageFilter,
                           nameof(IPageFilter.OnPageHandlerExecuted),
                           filter);

                        filter.OnPageHandlerExecuted(handlerExecutedContext);

                        _diagnosticListener.AfterOnPageHandlerExecuted(handlerExecutedContext, filter);
                        _logger.AfterExecutingMethodOnFilter(
                           PageLoggerExtensions.PageFilter,
                           nameof(IPageFilter.OnPageHandlerExecuted),
                           filter);

                        goto case State.PageEnd;
                    }

                case State.PageInside:
                    {
                        var task = InvokeHandlerMethodAsync();
                        if (task.Status != TaskStatus.RanToCompletion)
                        {
                            next = State.PageEnd;
                            return task;
                        }

                        goto case State.PageEnd;
                    }

                case State.PageEnd:
                    {
                        if (scope == Scope.Page)
                        {
                            if (_handlerExecutedContext == null)
                            {
                                _handlerExecutedContext = new PageHandlerExecutedContext(_pageContext, _filters, _handler, _instance)
                                {
                                    Result = _result,
                                };
                            }

                            isCompleted = true;
                            return Task.CompletedTask;
                        }

                        var handlerExecutedContext = _handlerExecutedContext;
                        Rethrow(handlerExecutedContext);

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

                        isCompleted = true;
                        return Task.CompletedTask;
                    }

                default:
                    throw new InvalidOperationException();
            }
        }
예제 #25
0
        public static PageHandlerBinderDelegate CreateHandlerBinder(
            ParameterBinder parameterBinder,
            IModelMetadataProvider modelMetadataProvider,
            IModelBinderFactory modelBinderFactory,
            CompiledPageActionDescriptor actionDescriptor,
            HandlerMethodDescriptor handler,
            MvcOptions mvcOptions)
        {
            if (handler.Parameters == null || handler.Parameters.Count == 0)
            {
                return(NullHandlerBinder);
            }

            var handlerType          = actionDescriptor.HandlerTypeInfo.AsType();
            var parameterBindingInfo = new BinderItem[handler.Parameters.Count];

            for (var i = 0; i < parameterBindingInfo.Length; i++)
            {
                var           parameter = handler.Parameters[i];
                ModelMetadata metadata;
                if (modelMetadataProvider is ModelMetadataProvider modelMetadataProviderBase)
                {
                    // The default model metadata provider derives from ModelMetadataProvider
                    // and can therefore supply information about attributes applied to parameters.
                    metadata = modelMetadataProviderBase.GetMetadataForParameter(parameter.ParameterInfo);
                }
                else
                {
                    // For backward compatibility, if there's a custom model metadata provider that
                    // only implements the older IModelMetadataProvider interface, access the more
                    // limited metadata information it supplies. In this scenario, validation attributes
                    // are not supported on parameters.
                    metadata = modelMetadataProvider.GetMetadataForType(parameter.ParameterType);
                }

                var binder = modelBinderFactory.CreateBinder(new ModelBinderFactoryContext
                {
                    BindingInfo = parameter.BindingInfo,
                    Metadata    = metadata,
                    CacheToken  = parameter,
                });

                parameterBindingInfo[i] = new BinderItem(binder, metadata);
            }

            return(Bind);

            async Task Bind(PageContext pageContext, IDictionary <string, object?> arguments)
            {
                var(success, valueProvider) = await CompositeValueProvider.TryCreateAsync(pageContext, pageContext.ValueProviderFactories);

                if (!success)
                {
                    return;
                }

                for (var i = 0; i < parameterBindingInfo.Length; i++)
                {
                    var parameter     = handler.Parameters[i];
                    var bindingInfo   = parameterBindingInfo[i];
                    var modelMetadata = bindingInfo.ModelMetadata;

                    if (!modelMetadata.IsBindingAllowed)
                    {
                        continue;
                    }

                    var result = await parameterBinder.BindModelAsync(
                        pageContext,
                        bindingInfo.ModelBinder,
                        valueProvider !,
                        parameter,
                        modelMetadata,
                        value : null,
                        container : null); // Parameters do not have containers.

                    if (result.IsModelSet)
                    {
                        arguments[parameter.Name] = result.Model;
                    }
                }
            }
        }
 public static HandlerMethodDescriptorDebugObject GetDebugObject(this HandlerMethodDescriptor handlerMethodDescriptor) => new HandlerMethodDescriptorDebugObject(handlerMethodDescriptor);