public void PopulateHandlerMethods_IgnoresMethodWithNonHandlerAttribute() { // Arrange var provider = new DefaultPageApplicationModelProvider(); var typeInfo = typeof(PageWithNonHandlerMethod).GetTypeInfo(); var expected = typeInfo.GetMethod(nameof(PageWithNonHandlerMethod.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); }); }
// 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 PopulateHandlerProperties_UsesPropertyHelpers_ToFindProperties() { // Arrange var provider = new DefaultPageApplicationModelProvider(); 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()); }); }
/// <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; EndpointMetadata = new List <object>(other.EndpointMetadata); }
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); }); }
/// <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); var message = "invalid model type"; 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)); }
public void Load_InvokesApplicationModelConventions() { // Arrange var descriptor = new PageActionDescriptor(); var compilerProvider = GetCompilerProvider(); var model = new PageApplicationModel(descriptor, typeof(object).GetTypeInfo(), new object[0]); var provider = new Mock <IPageApplicationModelProvider>(); provider.Setup(p => p.OnProvidersExecuting(It.IsAny <PageApplicationModelProviderContext>())) .Callback((PageApplicationModelProviderContext c) => { c.PageApplicationModel = model; }); var providers = new[] { provider.Object }; var razorPagesOptions = new TestOptionsManager <RazorPagesOptions>(); var mvcOptions = new TestOptionsManager <MvcOptions>(); var convention = new Mock <IPageApplicationModelConvention>(); convention.Setup(c => c.Apply(It.IsAny <PageApplicationModel>())) .Callback((PageApplicationModel m) => { Assert.Same(model, m); }); razorPagesOptions.Value.Conventions.Add(convention.Object); var loader = new DefaultPageLoader( providers, compilerProvider, razorPagesOptions, mvcOptions); // Act var result = loader.Load(new PageActionDescriptor()); // Assert convention.Verify(); }
public void OnProvidersExecuting_AddsFiltersToModel() { // Arrange var actionDescriptor = new PageActionDescriptor(); var applicationModel = new PageApplicationModel( actionDescriptor, typeof(object).GetTypeInfo(), new object[0]); var applicationModelProvider = new TempDataFilterPageApplicationModelProvider(); var context = new PageApplicationModelProviderContext(new PageActionDescriptor(), typeof(object).GetTypeInfo()) { PageApplicationModel = applicationModel, }; // Act applicationModelProvider.OnProvidersExecuting(context); // Assert Assert.Collection( applicationModel.Filters, filter => Assert.IsType <PageSaveTempDataPropertyFilterFactory>(filter)); }
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); } }
public void CreateHandlerModel_ParsesMethod() { // Arrange var provider = new DefaultPageApplicationModelProvider(); 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); }); }
public void OnProvidersExecuting_AddsFiltersToModel() { // Arrange var actionDescriptor = new PageActionDescriptor(); var applicationModel = new PageApplicationModel( actionDescriptor, typeof(object).GetTypeInfo(), new object[0]); var applicationModelProvider = new AutoValidateAntiforgeryPageApplicationModelProvider(); var context = new PageApplicationModelProviderContext(new PageActionDescriptor(), typeof(object).GetTypeInfo()) { PageApplicationModel = applicationModel, }; // Act applicationModelProvider.OnProvidersExecuting(context); // Assert Assert.Collection( applicationModel.Filters, filter => Assert.IsType <AutoValidateAntiforgeryTokenAttribute>(filter)); }
public void ApplyConventions_InvokesApplicationModelConventions() { // Arrange var descriptor = new PageActionDescriptor(); var model = new PageApplicationModel(descriptor, typeof(object).GetTypeInfo(), Array.Empty <object>()); var convention = new Mock <IPageApplicationModelConvention>(); convention.Setup(c => c.Apply(It.IsAny <PageApplicationModel>())) .Callback((PageApplicationModel m) => { Assert.Same(model, m); }) .Verifiable(); var conventionCollection = new PageConventionCollection() { convention.Object, }; // Act RuntimeRazorPageLoader.ApplyConventions(conventionCollection, model); // Assert convention.Verify(); }
public async Task LoadAsync_InvokesApplicationModelProviders() { // Arrange var descriptor = new PageActionDescriptor(); var compilerProvider = GetCompilerProvider(); var mvcOptions = Options.Create(new MvcOptions()); var endpointFactory = new ActionEndpointFactory(Mock.Of <RoutePatternTransformer>(), Enumerable.Empty <IRequestDelegateFactory>(), Mock.Of <IServiceProvider>()); var provider1 = new Mock <IPageApplicationModelProvider>(); var provider2 = new Mock <IPageApplicationModelProvider>(); var sequence = 0; var pageApplicationModel1 = new PageApplicationModel(descriptor, typeof(object).GetTypeInfo(), Array.Empty <object>()); var pageApplicationModel2 = new PageApplicationModel(descriptor, typeof(object).GetTypeInfo(), Array.Empty <object>()); provider1.Setup(p => p.OnProvidersExecuting(It.IsAny <PageApplicationModelProviderContext>())) .Callback((PageApplicationModelProviderContext c) => { Assert.Equal(0, sequence++); Assert.Null(c.PageApplicationModel); c.PageApplicationModel = pageApplicationModel1; }) .Verifiable(); provider2.Setup(p => p.OnProvidersExecuting(It.IsAny <PageApplicationModelProviderContext>())) .Callback((PageApplicationModelProviderContext c) => { Assert.Equal(1, sequence++); Assert.Same(pageApplicationModel1, c.PageApplicationModel); c.PageApplicationModel = pageApplicationModel2; }) .Verifiable(); provider1.Setup(p => p.OnProvidersExecuted(It.IsAny <PageApplicationModelProviderContext>())) .Callback((PageApplicationModelProviderContext c) => { Assert.Equal(3, sequence++); Assert.Same(pageApplicationModel2, c.PageApplicationModel); }) .Verifiable(); provider2.Setup(p => p.OnProvidersExecuted(It.IsAny <PageApplicationModelProviderContext>())) .Callback((PageApplicationModelProviderContext c) => { Assert.Equal(2, sequence++); Assert.Same(pageApplicationModel2, c.PageApplicationModel); }) .Verifiable(); var providers = new[] { provider1.Object, provider2.Object }; var loader = new DefaultPageLoader( providers, compilerProvider, endpointFactory, RazorPagesOptions, mvcOptions); // Act var result = await loader.LoadAsync(new PageActionDescriptor(), EndpointMetadataCollection.Empty); // Assert provider1.Verify(); provider2.Verify(); }
/// <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(); // 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, handlerType, handlerTypeAttributes) { PageType = pageTypeInfo, ModelType = modelTypeInfo, }; PopulateHandlerMethods(pageModel); PopulateHandlerProperties(pageModel); PopulateFilters(pageModel); return(pageModel); }
public void Load_InvokesApplicationModelProviders() { // Arrange var descriptor = new PageActionDescriptor(); var compilerProvider = GetCompilerProvider(); var razorPagesOptions = Options.Create(new RazorPagesOptions()); var mvcOptions = Options.Create(new MvcOptions()); var provider1 = new Mock <IPageApplicationModelProvider>(); var provider2 = new Mock <IPageApplicationModelProvider>(); var sequence = 0; var pageApplicationModel1 = new PageApplicationModel(descriptor, typeof(object).GetTypeInfo(), Array.Empty <object>()); var pageApplicationModel2 = new PageApplicationModel(descriptor, typeof(object).GetTypeInfo(), Array.Empty <object>()); provider1.Setup(p => p.OnProvidersExecuting(It.IsAny <PageApplicationModelProviderContext>())) .Callback((PageApplicationModelProviderContext c) => { Assert.Equal(0, sequence++); Assert.Null(c.PageApplicationModel); c.PageApplicationModel = pageApplicationModel1; }) .Verifiable(); provider2.Setup(p => p.OnProvidersExecuting(It.IsAny <PageApplicationModelProviderContext>())) .Callback((PageApplicationModelProviderContext c) => { Assert.Equal(1, sequence++); Assert.Same(pageApplicationModel1, c.PageApplicationModel); c.PageApplicationModel = pageApplicationModel2; }) .Verifiable(); provider1.Setup(p => p.OnProvidersExecuted(It.IsAny <PageApplicationModelProviderContext>())) .Callback((PageApplicationModelProviderContext c) => { Assert.Equal(3, sequence++); Assert.Same(pageApplicationModel2, c.PageApplicationModel); }) .Verifiable(); provider2.Setup(p => p.OnProvidersExecuted(It.IsAny <PageApplicationModelProviderContext>())) .Callback((PageApplicationModelProviderContext c) => { Assert.Equal(2, sequence++); Assert.Same(pageApplicationModel2, c.PageApplicationModel); }) .Verifiable(); var providers = new[] { provider1.Object, provider2.Object }; var loader = new DefaultPageLoader( providers, compilerProvider, razorPagesOptions, mvcOptions); // Act var result = loader.Load(new PageActionDescriptor()); // Assert provider1.Verify(); provider2.Verify(); }
public void Apply(PageApplicationModel model) { model.Filters.Add(new AddHeaderAttribute("Author", "Go")); }
public async Task LoadAsync_UpdatesResults() { // Arrange var descriptor = new PageActionDescriptor() { AttributeRouteInfo = new AttributeRouteInfo() { Template = "/test", }, }; var transformer = new Mock <RoutePatternTransformer>(); transformer .Setup(t => t.SubstituteRequiredValues(It.IsAny <RoutePattern>(), It.IsAny <object>())) .Returns <RoutePattern, object>((p, v) => p); var compilerProvider = GetCompilerProvider(); var razorPagesOptions = Options.Create(new RazorPagesOptions()); var mvcOptions = Options.Create(new MvcOptions()); var endpointFactory = new ActionEndpointFactory(transformer.Object); var provider = new Mock <IPageApplicationModelProvider>(); var pageApplicationModel = new PageApplicationModel(descriptor, typeof(object).GetTypeInfo(), Array.Empty <object>()); provider.Setup(p => p.OnProvidersExecuting(It.IsAny <PageApplicationModelProviderContext>())) .Callback((PageApplicationModelProviderContext c) => { Assert.Null(c.PageApplicationModel); c.PageApplicationModel = pageApplicationModel; }) .Verifiable(); var providers = new[] { provider.Object, }; var descriptorCollection1 = new ActionDescriptorCollection(new[] { descriptor }, version: 1); var descriptorCollection2 = new ActionDescriptorCollection(new[] { descriptor }, version: 2); var actionDescriptorCollectionProvider = new Mock <IActionDescriptorCollectionProvider>(); actionDescriptorCollectionProvider .SetupSequence(p => p.ActionDescriptors) .Returns(descriptorCollection1) .Returns(descriptorCollection2); var loader = new DefaultPageLoader( actionDescriptorCollectionProvider.Object, providers, compilerProvider, endpointFactory, razorPagesOptions, mvcOptions); // Act var result1 = await loader.LoadAsync(descriptor); var result2 = await loader.LoadAsync(descriptor); // Assert Assert.NotSame(result1, result2); }
public void Apply(PageApplicationModel model) { var featureName = GetFeatureName(model.ModelType); model.Properties.Add("feature", featureName); }
public void Apply(PageApplicationModel model) { model.Filters.Add(new AddHeaderAttribute( "GlobalHeader", new string[] { "Global Header Value" })); }
/// <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> private 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); }