示例#1
0
        public void PopulateHandlerMethods_IgnoresAbstractMethods()
        {
            // Arrange
            var provider  = CreateProvider();
            var typeInfo  = typeof(PageModelWithAbstractMethod).GetTypeInfo();
            var expected  = typeInfo.GetMethod(nameof(PageModelWithAbstractMethod.OnGet), BindingFlags.Public | BindingFlags.Instance);
            var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);

            // Act
            provider.PopulateHandlerMethods(pageModel);

            // Assert
            var handlerMethods = pageModel.HandlerMethods;

            Assert.Collection(
                handlerMethods,
                handler => Assert.Same(expected, handler.MethodInfo));
        }
        public void CreateDescriptor_AddsGlobalFiltersWithTheRightScope()
        {
            // Arrange
            var actionDescriptor = new PageActionDescriptor
            {
                ActionConstraints  = new List <IActionConstraintMetadata>(),
                AttributeRouteInfo = new AttributeRouteInfo(),
                FilterDescriptors  = new List <FilterDescriptor>(),
                RelativePath       = "/Foo",
                RouteValues        = new Dictionary <string, string>(),
                ViewEnginePath     = "/Pages/Foo",
            };
            var handlerTypeInfo      = typeof(TestModel).GetTypeInfo();
            var pageApplicationModel = new PageApplicationModel(actionDescriptor, handlerTypeInfo, new object[0])
            {
                PageType  = typeof(TestPage).GetTypeInfo(),
                ModelType = typeof(TestModel).GetTypeInfo(),
                Filters   =
                {
                    Mock.Of <IFilterMetadata>(),
                },
            };
            var globalFilters = new FilterCollection
            {
                Mock.Of <IFilterMetadata>(),
            };

            // Act
            var compiledPageActionDescriptor = CompiledPageActionDescriptorBuilder.Build(pageApplicationModel, globalFilters);

            // Assert
            Assert.Collection(
                compiledPageActionDescriptor.FilterDescriptors,
                filterDescriptor =>
            {
                Assert.Same(globalFilters[0], filterDescriptor.Filter);
                Assert.Equal(FilterScope.Global, filterDescriptor.Scope);
            },
                filterDescriptor =>
            {
                Assert.Same(pageApplicationModel.Filters[0], filterDescriptor.Filter);
                Assert.Equal(FilterScope.Action, filterDescriptor.Scope);
            });
        }
示例#3
0
        /// <summary>
        /// A copy constructor for <see cref="PageApplicationModel"/>.
        /// </summary>
        /// <param name="other">The <see cref="PageApplicationModel"/> to copy from.</param>
        public PageApplicationModel(PageApplicationModel other)
        {
            if (other == null)
            {
                throw new ArgumentNullException(nameof(other));
            }

            ActionDescriptor = other.ActionDescriptor;
            HandlerType      = other.HandlerType;
            PageType         = other.PageType;
            ModelType        = other.ModelType;

            Filters    = new List <IFilterMetadata>(other.Filters);
            Properties = new Dictionary <object, object>(other.Properties);

            HandlerMethods        = new List <PageHandlerModel>(other.HandlerMethods.Select(m => new PageHandlerModel(m)));
            HandlerProperties     = new List <PagePropertyModel>(other.HandlerProperties.Select(p => new PagePropertyModel(p)));
            HandlerTypeAttributes = other.HandlerTypeAttributes;
        }
示例#4
0
        public void PopulateHandlerProperties_UsesPropertyHelpers_ToFindProperties()
        {
            // Arrange
            var provider  = CreateProvider();
            var typeInfo  = typeof(HidesAProperty).GetTypeInfo();
            var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);

            // Act
            provider.PopulateHandlerProperties(pageModel);

            // Assert
            var properties = pageModel.HandlerProperties;

            Assert.Collection(
                properties,
                p =>
            {
                Assert.Equal(typeof(HidesAProperty).GetTypeInfo(), p.PropertyInfo.DeclaringType.GetTypeInfo());
            });
        }
示例#5
0
        // Internal for unit testing
        internal static HandlerMethodDescriptor[] CreateHandlerMethods(PageApplicationModel applicationModel)
        {
            var handlerModels      = applicationModel.HandlerMethods;
            var handlerDescriptors = new HandlerMethodDescriptor[handlerModels.Count];

            for (var i = 0; i < handlerDescriptors.Length; i++)
            {
                var handlerModel = handlerModels[i];

                handlerDescriptors[i] = new HandlerMethodDescriptor
                {
                    HttpMethod = handlerModel.HttpMethod,
                    Name       = handlerModel.HandlerName,
                    MethodInfo = handlerModel.MethodInfo,
                    Parameters = CreateHandlerParameters(handlerModel),
                };
            }

            return(handlerDescriptors);
        }
        public void CreateBoundProperties_IgnoresPropertiesWithoutBindingInfo()
        {
            // Arrange
            var actionDescriptor = new PageActionDescriptor();
            var handlerTypeInfo  = typeof(HandlerWithIgnoredProperties).GetTypeInfo();
            var propertyModel1   = new PagePropertyModel(
                handlerTypeInfo.GetProperty(nameof(HandlerWithIgnoredProperties.Property)),
                new object[0])
            {
                PropertyName = nameof(HandlerWithIgnoredProperties.Property),
                BindingInfo  = new BindingInfo(),
            };
            var propertyModel2 = new PagePropertyModel(
                handlerTypeInfo.GetProperty(nameof(HandlerWithIgnoredProperties.IgnoreMe)),
                new object[0])
            {
                PropertyName = nameof(HandlerWithIgnoredProperties.IgnoreMe),
            };
            var pageApplicationModel = new PageApplicationModel(actionDescriptor, handlerTypeInfo, new object[0])
            {
                HandlerProperties =
                {
                    propertyModel1,
                    propertyModel2,
                }
            };

            // Act
            var propertyDescriptors = CompiledPageActionDescriptorBuilder.CreateBoundProperties(pageApplicationModel);

            // Assert
            Assert.Collection(
                propertyDescriptors,
                p =>
            {
                Assert.Same(propertyModel1.PropertyName, p.Name);
                Assert.Same(typeof(int), p.ParameterType);
                Assert.Same(propertyModel1.PropertyInfo, p.Property);
                Assert.Same(propertyModel1.BindingInfo, p.BindingInfo);
            });
        }
示例#7
0
        /// <summary>
        /// Creates a <see cref="CompiledPageActionDescriptor"/> from the specified <paramref name="applicationModel"/>.
        /// </summary>
        /// <param name="applicationModel">The <see cref="PageApplicationModel"/>.</param>
        /// <param name="globalFilters">Global filters to apply to the page.</param>
        /// <returns>The <see cref="CompiledPageActionDescriptor"/>.</returns>
        public static CompiledPageActionDescriptor Build(
            PageApplicationModel applicationModel,
            FilterCollection globalFilters)
        {
            var boundProperties = CreateBoundProperties(applicationModel);
            var filters         = Enumerable.Concat(
                globalFilters.Select(f => new FilterDescriptor(f, FilterScope.Global)),
                applicationModel.Filters.Select(f => new FilterDescriptor(f, FilterScope.Action)))
                                  .ToArray();
            var handlerMethods = CreateHandlerMethods(applicationModel);

            if (applicationModel.ModelType != null && applicationModel.DeclaredModelType != null &&
                !applicationModel.DeclaredModelType.IsAssignableFrom(applicationModel.ModelType))
            {
                var message = Resources.FormatInvalidActionDescriptorModelType(
                    applicationModel.ActionDescriptor.DisplayName,
                    applicationModel.ModelType.Name,
                    applicationModel.DeclaredModelType.Name);

                throw new InvalidOperationException(message);
            }

            var actionDescriptor = applicationModel.ActionDescriptor;

            return(new CompiledPageActionDescriptor(actionDescriptor)
            {
                ActionConstraints = actionDescriptor.ActionConstraints,
                AttributeRouteInfo = actionDescriptor.AttributeRouteInfo,
                BoundProperties = boundProperties,
                EndpointMetadata = CreateEndPointMetadata(applicationModel),
                FilterDescriptors = filters,
                HandlerMethods = handlerMethods,
                HandlerTypeInfo = applicationModel.HandlerType,
                DeclaredModelTypeInfo = applicationModel.DeclaredModelType,
                ModelTypeInfo = applicationModel.ModelType,
                RouteValues = actionDescriptor.RouteValues,
                PageTypeInfo = applicationModel.PageType,
                Properties = applicationModel.Properties,
            });
        }
        public void CreateDescriptor_ThrowsIfModelIsNotCompatibleWithDeclaredModel()
        {
            // Arrange
            var actionDescriptor = new PageActionDescriptor
            {
                ActionConstraints  = new List <IActionConstraintMetadata>(),
                AttributeRouteInfo = new AttributeRouteInfo(),
                FilterDescriptors  = new List <FilterDescriptor>(),
                RelativePath       = "/Foo",
                RouteValues        = new Dictionary <string, string>(),
                ViewEnginePath     = "/Pages/Foo",
            };
            var handlerTypeInfo      = typeof(TestModel).GetTypeInfo();
            var pageApplicationModel = new PageApplicationModel(actionDescriptor, typeof(TestModel).GetTypeInfo(), handlerTypeInfo, new object[0])
            {
                PageType  = typeof(TestPage).GetTypeInfo(),
                ModelType = typeof(string).GetTypeInfo(),
                Filters   =
                {
                    Mock.Of <IFilterMetadata>(),
                    Mock.Of <IFilterMetadata>(),
                },
                HandlerMethods =
                {
                    new PageHandlerModel(handlerTypeInfo.GetMethod(nameof(TestModel.OnGet)), new object[0]),
                },
                HandlerProperties =
                {
                    new PagePropertyModel(handlerTypeInfo.GetProperty(nameof(TestModel.Property)), new object[0])
                    {
                        BindingInfo = new BindingInfo(),
                    },
                }
            };
            var globalFilters = new FilterCollection();

            // Act & Assert
            var actual = Assert.Throws <InvalidOperationException>(() =>
                                                                   CompiledPageActionDescriptorBuilder.Build(pageApplicationModel, globalFilters));
        }
示例#9
0
        public void CreateHandlerModel_ParsesMethod()
        {
            // Arrange
            var provider  = CreateProvider();
            var typeInfo  = typeof(PageModelWithHandlerNames).GetTypeInfo();
            var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);

            // Act
            provider.PopulateHandlerMethods(pageModel);

            // Assert
            var handlerMethods = pageModel.HandlerMethods;

            Assert.Collection(
                handlerMethods.OrderBy(h => h.MethodInfo.Name),
                handler =>
            {
                Assert.Same(typeInfo.GetMethod(nameof(PageModelWithHandlerNames.OnPutDeleteAsync)), handler.MethodInfo);
                Assert.Equal("Put", handler.HttpMethod);
                Assert.Equal("Delete", handler.HandlerName);
            });
        }
示例#10
0
        public void CreateHandlerMethods_WithLegacyValidationBehavior_AddsParameterDescriptors()
        {
            // Arrange
            var provider = new DefaultPageApplicationModelProvider(
                TestModelMetadataProvider.CreateDefaultProvider(),
                Options.Create(new MvcOptions {
                AllowValidatingTopLevelNodes = false
            }),
                Options.Create(new RazorPagesOptions()));
            var typeInfo  = typeof(PageWithHandlerParameters).GetTypeInfo();
            var expected  = typeInfo.GetMethod(nameof(PageWithHandlerParameters.OnPost));
            var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);

            // Act
            provider.PopulateHandlerMethods(pageModel);

            // Assert
            var handlerMethods = pageModel.HandlerMethods;
            var handler        = Assert.Single(handlerMethods);

            Assert.Collection(
                handler.Parameters,
                p =>
            {
                Assert.NotNull(p.ParameterInfo);
                Assert.Equal(typeof(string), p.ParameterInfo.ParameterType);
                Assert.Equal("name", p.ParameterName);
            },
                p =>
            {
                Assert.NotNull(p.ParameterInfo);
                Assert.Equal(typeof(int), p.ParameterInfo.ParameterType);
                Assert.Equal("id", p.ParameterName);
                Assert.Equal("personId", p.BindingInfo.BinderModelName);
            });
        }
        internal void PopulateFilters(PageApplicationModel pageModel)
        {
            for (var i = 0; i < pageModel.HandlerTypeAttributes.Count; i++)
            {
                if (pageModel.HandlerTypeAttributes[i] is IFilterMetadata filter)
                {
                    pageModel.Filters.Add(filter);
                }
            }

            if (typeof(IAsyncPageFilter).IsAssignableFrom(pageModel.HandlerType) ||
                typeof(IPageFilter).IsAssignableFrom(pageModel.HandlerType))
            {
                pageModel.Filters.Add(_pageHandlerPageFilter);
            }

            if (typeof(IAsyncResultFilter).IsAssignableFrom(pageModel.HandlerType) ||
                typeof(IResultFilter).IsAssignableFrom(pageModel.HandlerType))
            {
                pageModel.Filters.Add(_pageHandlerResultFilter);
            }

            pageModel.Filters.Add(_handleOptionsRequestsFilter);
        }
        /// <summary>
        /// Creates a <see cref="PageApplicationModel"/> for the given <paramref name="pageTypeInfo"/>.
        /// </summary>
        /// <param name="actionDescriptor">The <see cref="PageActionDescriptor"/>.</param>
        /// <param name="pageTypeInfo">The <see cref="TypeInfo"/>.</param>
        /// <returns>A <see cref="PageApplicationModel"/> for the given <see cref="TypeInfo"/>.</returns>
        protected virtual PageApplicationModel CreateModel(
            PageActionDescriptor actionDescriptor,
            TypeInfo pageTypeInfo)
        {
            if (actionDescriptor == null)
            {
                throw new ArgumentNullException(nameof(actionDescriptor));
            }

            if (pageTypeInfo == null)
            {
                throw new ArgumentNullException(nameof(pageTypeInfo));
            }

            if (!typeof(PageBase).GetTypeInfo().IsAssignableFrom(pageTypeInfo))
            {
                throw new InvalidOperationException(Resources.FormatInvalidPageType_WrongBase(
                                                        pageTypeInfo.FullName,
                                                        typeof(PageBase).FullName));
            }

            // Pages always have a model type. If it's not set explicitly by the developer using
            // @model, it will be the same as the page type.
            var modelProperty = pageTypeInfo.GetProperty(ModelPropertyName, BindingFlags.Public | BindingFlags.Instance);

            if (modelProperty == null)
            {
                throw new InvalidOperationException(Resources.FormatInvalidPageType_NoModelProperty(
                                                        pageTypeInfo.FullName,
                                                        ModelPropertyName));
            }

            var modelTypeInfo     = modelProperty.PropertyType.GetTypeInfo();
            var declaredModelType = modelTypeInfo;

            // Now we want figure out which type is the handler type.
            TypeInfo handlerType;

            if (modelProperty.PropertyType.IsDefined(typeof(PageModelAttribute), inherit: true))
            {
                handlerType = modelTypeInfo;
            }
            else
            {
                handlerType = pageTypeInfo;
            }

            var handlerTypeAttributes = handlerType.GetCustomAttributes(inherit: true);
            var pageModel             = new PageApplicationModel(
                actionDescriptor,
                declaredModelType,
                handlerType,
                handlerTypeAttributes)
            {
                PageType  = pageTypeInfo,
                ModelType = modelTypeInfo,
            };

            PopulateHandlerMethods(pageModel);
            PopulateHandlerProperties(pageModel);
            PopulateFilters(pageModel);

            return(pageModel);
        }
        /// <summary>
        /// Creates a <see cref="PageApplicationModel"/> for the given <paramref name="pageTypeInfo"/>.
        /// </summary>
        /// <param name="actionDescriptor">The <see cref="PageActionDescriptor"/>.</param>
        /// <param name="pageTypeInfo">The <see cref="TypeInfo"/>.</param>
        /// <returns>A <see cref="PageApplicationModel"/> for the given <see cref="TypeInfo"/>.</returns>
        protected virtual PageApplicationModel CreateModel(
            PageActionDescriptor actionDescriptor,
            TypeInfo pageTypeInfo)
        {
            if (actionDescriptor == null)
            {
                throw new ArgumentNullException(nameof(actionDescriptor));
            }

            if (pageTypeInfo == null)
            {
                throw new ArgumentNullException(nameof(pageTypeInfo));
            }

            if (!typeof(PageBase).GetTypeInfo().IsAssignableFrom(pageTypeInfo))
            {
                throw new InvalidOperationException(Resources.FormatInvalidPageType_WrongBase(
                                                        pageTypeInfo.FullName,
                                                        typeof(PageBase).FullName));
            }

            // Pages always have a model type. If it's not set explicitly by the developer using
            // @model, it will be the same as the page type.
            var modelProperty = pageTypeInfo.GetProperty(ModelPropertyName, BindingFlags.Public | BindingFlags.Instance);

            if (modelProperty == null)
            {
                throw new InvalidOperationException(Resources.FormatInvalidPageType_NoModelProperty(
                                                        pageTypeInfo.FullName,
                                                        ModelPropertyName));
            }

            var modelTypeInfo     = modelProperty.PropertyType.GetTypeInfo();
            var declaredModelType = modelTypeInfo;

            // Now we want figure out which type is the handler type.
            TypeInfo handlerType;
            var      pageTypeAttributes = pageTypeInfo.GetCustomAttributes(inherit: true);

            object[] handlerTypeAttributes;
            if (modelProperty.PropertyType.IsDefined(typeof(PageModelAttribute), inherit: true))
            {
                handlerType = modelTypeInfo;

                // If a PageModel is specified, combine the attributes specified on the Page and the Model type.
                // Attributes that appear earlier in the are more significant. In this case, we'll treat attributes on the model (code)
                // to be more signficant than the page (code-generated).
                handlerTypeAttributes = modelTypeInfo.GetCustomAttributes(inherit: true).Concat(pageTypeAttributes).ToArray();
            }
            else
            {
                handlerType           = pageTypeInfo;
                handlerTypeAttributes = pageTypeInfo.GetCustomAttributes(inherit: true);
            }

            var pageModel = new PageApplicationModel(
                actionDescriptor,
                declaredModelType,
                handlerType,
                handlerTypeAttributes)
            {
                PageType  = pageTypeInfo,
                ModelType = modelTypeInfo,
            };

            PopulateHandlerMethods(pageModel);
            PopulateHandlerProperties(pageModel);
            PopulateFilters(pageModel);

            return(pageModel);
        }