public void GetViewStartFactories_FindsFullHierarchy()
    {
        // Arrange
        var descriptor = new PageActionDescriptor()
        {
            RelativePath      = "/Pages/Level1/Level2/Index.cshtml",
            FilterDescriptors = new FilterDescriptor[0],
            ViewEnginePath    = "/Pages/Level1/Level2/Index.cshtml"
        };

        var compiledPageDescriptor = new CompiledPageActionDescriptor(descriptor)
        {
            PageTypeInfo = typeof(object).GetTypeInfo(),
        };

        var loader = new Mock <PageLoader>();

        loader
        .Setup(l => l.LoadAsync(It.IsAny <PageActionDescriptor>(), It.IsAny <EndpointMetadataCollection>()))
        .ReturnsAsync(compiledPageDescriptor);

        var mock = new Mock <IRazorPageFactoryProvider>(MockBehavior.Strict);

        mock
        .Setup(p => p.CreateFactory("/Pages/Level1/Level2/_ViewStart.cshtml"))
        .Returns(new RazorPageFactoryResult(new CompiledViewDescriptor(), () => null))
        .Verifiable();
        mock
        .Setup(p => p.CreateFactory("/Pages/Level1/_ViewStart.cshtml"))
        .Returns(new RazorPageFactoryResult(new CompiledViewDescriptor(), () => null))
        .Verifiable();
        mock
        .Setup(p => p.CreateFactory("/Pages/_ViewStart.cshtml"))
        .Returns(new RazorPageFactoryResult(new CompiledViewDescriptor(), () => null))
        .Verifiable();
        mock
        .Setup(p => p.CreateFactory("/_ViewStart.cshtml"))
        .Returns(new RazorPageFactoryResult(new CompiledViewDescriptor(), () => null))
        .Verifiable();

        var razorPageFactoryProvider = mock.Object;

        var invokerProvider = CreateInvokerProvider(
            loader.Object,
            razorPageFactoryProvider: razorPageFactoryProvider);

        // Act
        var factories = invokerProvider.Cache.GetViewStartFactories(compiledPageDescriptor);

        // Assert
        mock.Verify();
    }
Example #2
0
        public async Task LoadAsync_CreatesEndpoint_WithRoute()
        {
            // 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 mvcOptions      = Options.Create(new MvcOptions());
            var endpointFactory = new PublicActionEndpointFactory(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 loader = new RuntimeRazorPageLoader(
                providers,
                compilerProvider,
                endpointFactory,
                RazorPagesOptions,
                mvcOptions);

            // Act
            var result = await loader.LoadAsync(descriptor);

            // Assert
            Assert.NotNull(result.Endpoint);
        }
        private async Task <CompiledPageActionDescriptor> LoadAsyncCore(PageActionDescriptor actionDescriptor, EndpointMetadataCollection endpointMetadata)
        {
            var viewDescriptor = await Compiler.CompileAsync(actionDescriptor.RelativePath);

            var context = new PageApplicationModelProviderContext(actionDescriptor, viewDescriptor.Type.GetTypeInfo());

            for (var i = 0; i < _applicationModelProviders.Length; i++)
            {
                _applicationModelProviders[i].OnProvidersExecuting(context);
            }

            for (var i = _applicationModelProviders.Length - 1; i >= 0; i--)
            {
                _applicationModelProviders[i].OnProvidersExecuted(context);
            }

            ApplyConventions(_conventions, context.PageApplicationModel);

            var compiled = PublicCompiledPageActionDescriptorBuilder.Build(context.PageApplicationModel, _globalFilters);

            // We need to create an endpoint for routing to use and attach it to the CompiledPageActionDescriptor...
            // routing for pages is two-phase. First we perform routing using the route info - we can do this without
            // compiling/loading the page. Then once we have a match we load the page and we can create an endpoint
            // with all of the information we get from the compiled action descriptor.
            var endpoints = new List <Endpoint>();

            _endpointFactory.AddEndpoints(
                endpoints,
                routeNames: new HashSet <string>(StringComparer.OrdinalIgnoreCase),
                action: compiled,
                routes: Array.Empty <PublicConventionalRouteEntry>(),
                conventions: new Action <EndpointBuilder>[]
            {
                b =>
                {
                    // Metadata from PageActionDescriptor is less significant than the one discovered from the compiled type.
                    // Consequently, we'll insert it at the beginning.
                    for (var i = endpointMetadata.Count - 1; i >= 0; i--)
                    {
                        b.Metadata.Insert(0, endpointMetadata[i]);
                    }
                },
            },
                createInertEndpoints: false);

            // In some test scenarios there's no route so the endpoint isn't created. This is fine because
            // it won't happen for real.
            compiled.Endpoint = endpoints.SingleOrDefault();

            return(compiled);
        }
Example #4
0
    public void CreateHandlerMethods_CopiesParameterDescriptorsFromParameterModel()
    {
        // Arrange
        var actionDescriptor = new PageActionDescriptor();
        var handlerTypeInfo  = typeof(HandlerWithParameters).GetTypeInfo();
        var handlerMethod    = handlerTypeInfo.GetMethod(nameof(HandlerWithParameters.OnPost));
        var parameters       = handlerMethod.GetParameters();
        var parameterModel1  = new PageParameterModel(parameters[0], new object[0])
        {
            ParameterName = "test-name"
        };
        var parameterModel2 = new PageParameterModel(parameters[1], new object[0])
        {
            BindingInfo = new BindingInfo(),
        };
        var handlerModel = new PageHandlerModel(handlerMethod, new object[0])
        {
            Parameters =
            {
                parameterModel1,
                parameterModel2,
            }
        };
        var pageApplicationModel = new PageApplicationModel(actionDescriptor, handlerTypeInfo, new object[0])
        {
            HandlerMethods =
            {
                handlerModel,
            }
        };

        // Act
        var handlerDescriptors = CompiledPageActionDescriptorBuilder.CreateHandlerMethods(pageApplicationModel);

        // Assert
        Assert.Collection(
            Assert.Single(handlerDescriptors).Parameters,
            p =>
        {
            Assert.Equal(parameters[0], p.ParameterInfo);
            Assert.Equal(typeof(string), p.ParameterType);
            Assert.Equal(parameterModel1.ParameterName, p.Name);
        },
            p =>
        {
            Assert.Equal(parameters[1], p.ParameterInfo);
            Assert.Equal(typeof(int), p.ParameterType);
            Assert.Same(parameterModel2.BindingInfo, p.BindingInfo);
        });
    }
        public void OnProvidersExecuting_CachesEntries()
        {
            // Arrange
            var descriptor = new PageActionDescriptor
            {
                RelativePath      = "Path1",
                FilterDescriptors = new FilterDescriptor[0],
            };

            var loader = new Mock <IPageLoader>();

            loader
            .Setup(l => l.Load(It.IsAny <PageActionDescriptor>()))
            .Returns(CreateCompiledPageActionDescriptor(descriptor));

            var invokerProvider = CreateInvokerProvider(
                loader.Object,
                CreateActionDescriptorCollection(descriptor));

            var context = new ActionInvokerProviderContext(new ActionContext
            {
                ActionDescriptor = descriptor,
                HttpContext      = new DefaultHttpContext(),
                RouteData        = new RouteData(),
            });

            // Act - 1
            invokerProvider.OnProvidersExecuting(context);

            // Assert - 1
            Assert.NotNull(context.Result);
            var actionInvoker = Assert.IsType <PageActionInvoker>(context.Result);
            var entry1        = actionInvoker.CacheEntry;

            // Act - 2
            context = new ActionInvokerProviderContext(new ActionContext
            {
                ActionDescriptor = descriptor,
                HttpContext      = new DefaultHttpContext(),
                RouteData        = new RouteData(),
            });
            invokerProvider.OnProvidersExecuting(context);

            // Assert - 2
            Assert.NotNull(context.Result);
            actionInvoker = Assert.IsType <PageActionInvoker>(context.Result);
            var entry2 = actionInvoker.CacheEntry;

            Assert.Same(entry1, entry2);
        }
        public void GetViewStartFactories_ReturnsFactoriesForFilesThatDoNotExistInProject()
        {
            // The factory provider might have access to _ViewStarts for files that do not exist on disk \ RazorProject.
            // This test verifies that we query the factory provider correctly.
            // Arrange
            var descriptor = new PageActionDescriptor()
            {
                RelativePath      = "/Views/Deeper/Index.cshtml",
                FilterDescriptors = new FilterDescriptor[0],
                ViewEnginePath    = "/Views/Deeper/Index.cshtml"
            };

            var loader = new Mock <IPageLoader>();

            loader
            .Setup(l => l.Load(It.IsAny <PageActionDescriptor>()))
            .Returns(CreateCompiledPageActionDescriptor(descriptor, typeof(TestPageModel)));

            var pageFactory = new Mock <IRazorPageFactoryProvider>();

            pageFactory
            .Setup(f => f.CreateFactory("/Views/Deeper/_ViewStart.cshtml"))
            .Returns(new RazorPageFactoryResult(new CompiledViewDescriptor(), () => null));
            pageFactory
            .Setup(f => f.CreateFactory("/Views/_ViewStart.cshtml"))
            .Returns(new RazorPageFactoryResult(new CompiledViewDescriptor(), razorPageFactory: null));
            pageFactory
            .Setup(f => f.CreateFactory("/_ViewStart.cshtml"))
            .Returns(new RazorPageFactoryResult(new CompiledViewDescriptor(), () => null));

            // No files
            var fileProvider = new TestFileProvider();
            var razorProject = new TestRazorProject(fileProvider, _hostingEnvironment);

            var invokerProvider = CreateInvokerProvider(
                loader.Object,
                CreateActionDescriptorCollection(descriptor),
                pageProvider: null,
                modelProvider: null,
                razorPageFactoryProvider: pageFactory.Object,
                razorProject: razorProject);

            var compiledDescriptor = CreateCompiledPageActionDescriptor(descriptor);

            // Act
            var factories = invokerProvider.GetViewStartFactories(compiledDescriptor).ToList();

            // Assert
            Assert.Equal(2, factories.Count);
        }
Example #7
0
    public void CreateDescriptor_CopiesPropertiesFromPageApplicationModel()
    {
        // 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(TestModel).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
        var actual = CompiledPageActionDescriptorBuilder.Build(pageApplicationModel, globalFilters);

        // Assert
        Assert.Same(pageApplicationModel.PageType, actual.PageTypeInfo);
        Assert.Same(pageApplicationModel.DeclaredModelType, actual.DeclaredModelTypeInfo);
        Assert.Same(pageApplicationModel.ModelType, actual.ModelTypeInfo);
        Assert.Same(pageApplicationModel.HandlerType, actual.HandlerTypeInfo);
        Assert.Same(pageApplicationModel.Properties, actual.Properties);
        Assert.Equal(pageApplicationModel.Filters, actual.FilterDescriptors.Select(f => f.Filter));
        Assert.Equal(pageApplicationModel.HandlerMethods.Select(p => p.MethodInfo), actual.HandlerMethods.Select(p => p.MethodInfo));
        Assert.Equal(pageApplicationModel.HandlerProperties.Select(p => p.PropertyName), actual.BoundProperties.Select(p => p.Name));
    }
Example #8
0
        public void OnProvidersExecuting_ThrowsIfPageDoesNotDeriveFromValidBaseType()
        {
            // Arrange
            var provider   = CreateProvider();
            var typeInfo   = typeof(InvalidPageWithWrongBaseClass).GetTypeInfo();
            var descriptor = new PageActionDescriptor();
            var context    = new PageApplicationModelProviderContext(descriptor, typeInfo);

            // Act & Assert
            var ex = Assert.Throws <InvalidOperationException>(() => provider.OnProvidersExecuting(context));

            // Assert
            Assert.Equal(
                $"The type '{typeInfo.FullName}' is not a valid page. A page must inherit from '{typeof(PageBase).FullName}'.",
                ex.Message);
        }
Example #9
0
        public void OnProvidersExecuting_ThrowsIfModelPropertyIsNotPublic()
        {
            // Arrange
            var provider   = CreateProvider();
            var typeInfo   = typeof(PageWithNonVisibleModel).GetTypeInfo();
            var descriptor = new PageActionDescriptor();
            var context    = new PageApplicationModelProviderContext(descriptor, typeInfo);

            // Act & Assert
            var ex = Assert.Throws <InvalidOperationException>(() => provider.OnProvidersExecuting(context));

            // Assert
            Assert.Equal(
                $"The type '{typeInfo.FullName}' is not a valid page. A page must define a public, non-static 'Model' property.",
                ex.Message);
        }
Example #10
0
        /// <summary>
        /// Initializes a new instance of <see cref="PageApplicationModel"/>.
        /// </summary>
        public PageApplicationModel(
            PageActionDescriptor actionDescriptor,
            TypeInfo handlerType,
            IReadOnlyList <object> handlerAttributes)
        {
            ActionDescriptor = actionDescriptor ?? throw new ArgumentNullException(nameof(actionDescriptor));
            HandlerType      = handlerType;

            Filters    = new List <IFilterMetadata>();
            Properties = new CopyOnWriteDictionary <object, object>(
                actionDescriptor.Properties,
                EqualityComparer <object> .Default);
            HandlerMethods        = new List <PageHandlerModel>();
            HandlerProperties     = new List <PagePropertyModel>();
            HandlerTypeAttributes = handlerAttributes;
        }
    public void SignOutNoScheme_SignsOutDefaultCookiesAndDefaultOpenIDConnectAADAzureADSchemesAsync()
    {
        // Arrange
        var options = new AzureADOptions()
        {
            CookieSchemeName        = AzureADDefaults.CookieScheme,
            OpenIdConnectSchemeName = AzureADDefaults.OpenIdScheme
        };

        var controllerContext = CreateControllerContext(
            CreateAuthenticatedPrincipal(AzureADDefaults.AuthenticationScheme));

        var descriptor = new PageActionDescriptor()
        {
            AttributeRouteInfo = new AttributeRouteInfo()
            {
                Template = "/Account/SignedOut"
            }
        };
        var controller = new AccountController(new OptionsMonitor(AzureADDefaults.AuthenticationScheme, options))
        {
            Url = new TestUrlHelper(
                controllerContext.HttpContext,
                new RouteData(),
                descriptor,
                "/Account/SignedOut",
                "https://localhost/Account/SignedOut"),
            ControllerContext = new ControllerContext()
            {
                HttpContext = controllerContext.HttpContext
            }
        };

        controller.Request.Scheme = "https";

        // Act
        var result = controller.SignOut(null);

        // Assert
        var signOut = Assert.IsAssignableFrom <SignOutResult>(result);

        Assert.Equal(new[] { AzureADDefaults.CookieScheme, AzureADDefaults.OpenIdScheme }, signOut.AuthenticationSchemes);
        Assert.NotNull(signOut.Properties.RedirectUri);
        Assert.Equal("https://localhost/Account/SignedOut", signOut.Properties.RedirectUri);
    }
Example #12
0
    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);
        });
    }
    public async Task SignOutProvidedScheme_SignsOutCustomCookiesAndCustomOpenIDConnectAADAzureADB2CSchemesAsync()
    {
        // Arrange
        var options = new AzureADB2COptions()
        {
            CookieSchemeName        = "Cookie",
            OpenIdConnectSchemeName = "OpenID"
        };

        var controllerContext = CreateControllerContext(
            CreateAuthenticatedPrincipal(AzureADB2CDefaults.AuthenticationScheme));
        var descriptor = new PageActionDescriptor()
        {
            AttributeRouteInfo = new AttributeRouteInfo()
            {
                Template = "/Account/SignedOut"
            }
        };

        var controller = new AccountController(new OptionsMonitor("Custom", options))
        {
            Url = new TestUrlHelper(
                controllerContext.HttpContext,
                new RouteData(),
                descriptor,
                "/Account/SignedOut",
                "https://localhost/Account/SignedOut"),
            ControllerContext = new ControllerContext()
            {
                HttpContext = controllerContext.HttpContext
            }
        };

        controller.Request.Scheme = "https";

        // Act
        var result = await controller.SignOut("Custom");

        // Assert
        var signOut = Assert.IsAssignableFrom <SignOutResult>(result);

        Assert.Equal(new[] { "Cookie", "OpenID" }, signOut.AuthenticationSchemes);
    }
Example #14
0
    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);
        });
    }
Example #15
0
        public void OnProvidersExecuting_DiscoversHandlersFromPage()
        {
            // Arrange
            var provider   = CreateProvider();
            var typeInfo   = typeof(PageWithModelWithoutHandlers).GetTypeInfo();
            var descriptor = new PageActionDescriptor();
            var context    = new PageApplicationModelProviderContext(descriptor, typeInfo);

            // Act
            provider.OnProvidersExecuting(context);

            // Assert
            Assert.NotNull(context.PageApplicationModel);
            Assert.Collection(
                context.PageApplicationModel.HandlerMethods.OrderBy(p => p.Name),
                handler =>
            {
                var name = nameof(PageWithModelWithoutHandlers.OnGet);
                Assert.Equal(typeInfo.GetMethod(name), handler.MethodInfo);
                Assert.Equal(name, handler.Name);
                Assert.Equal("Get", handler.HttpMethod);
                Assert.Null(handler.HandlerName);
            },
                handler =>
            {
                var name = nameof(PageWithModelWithoutHandlers.OnPostAsync);
                Assert.Equal(typeInfo.GetMethod(name), handler.MethodInfo);
                Assert.Equal(name, handler.Name);
                Assert.Equal("Post", handler.HttpMethod);
                Assert.Null(handler.HandlerName);
            },
                handler =>
            {
                var name = nameof(PageWithModelWithoutHandlers.OnPostDeleteCustomerAsync);
                Assert.Equal(typeInfo.GetMethod(name), handler.MethodInfo);
                Assert.Equal(name, handler.Name);
                Assert.Equal("Post", handler.HttpMethod);
                Assert.Equal("DeleteCustomer", handler.HandlerName);
            });
        }
    public void OnProvidersExecuting_DiscoversPropertiesFromModel()
    {
        // Arrange
        var provider   = CreateProvider();
        var typeInfo   = typeof(PageWithModel).GetTypeInfo();
        var modelType  = typeof(TestPageModel);
        var descriptor = new PageActionDescriptor();
        var context    = new PageApplicationModelProviderContext(descriptor, typeInfo);

        // Act
        provider.OnProvidersExecuting(context);

        // Assert
        Assert.NotNull(context.PageApplicationModel);
        Assert.Collection(
            context.PageApplicationModel.HandlerProperties.OrderBy(p => p.PropertyName),
            property =>
        {
            var name = nameof(TestPageModel.Property1);
            Assert.Equal(modelType.GetProperty(name), property.PropertyInfo);
            Assert.Null(property.BindingInfo);
            Assert.Equal(name, property.PropertyName);
        },
            property =>
        {
            var name = nameof(TestPageModel.Property2);
            Assert.Equal(modelType.GetProperty(name), property.PropertyInfo);
            Assert.Equal(name, property.PropertyName);
            Assert.NotNull(property.BindingInfo);
            Assert.Equal(BindingSource.Query, property.BindingInfo.BindingSource);
        },
            property =>
        {
            var name = nameof(TestPageModel.TestService);
            Assert.Equal(modelType.GetProperty(name), property.PropertyInfo);
            Assert.Equal(name, property.PropertyName);
            Assert.NotNull(property.BindingInfo);
            Assert.Equal(BindingSource.Services, property.BindingInfo.BindingSource);
        });
    }
Example #17
0
    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();
        }
Example #19
0
        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 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));
        }
        private static CompiledPageActionDescriptor CreateCompiledPageActionDescriptor(
            PageActionDescriptor descriptor,
            Type pageType = null)
        {
            pageType = pageType ?? typeof(object);
            var pageTypeInfo = pageType.GetTypeInfo();

            TypeInfo modelTypeInfo = null;

            if (pageType != null)
            {
                modelTypeInfo = pageTypeInfo.GetProperty("Model")?.PropertyType.GetTypeInfo();
            }

            return(new CompiledPageActionDescriptor(descriptor)
            {
                HandlerTypeInfo = modelTypeInfo ?? pageTypeInfo,
                ModelTypeInfo = modelTypeInfo ?? pageTypeInfo,
                PageTypeInfo = pageTypeInfo,
                FilterDescriptors = Array.Empty <FilterDescriptor>(),
            });
        }
Example #22
0
    private async Task <CompiledPageActionDescriptor> LoadAsyncCore(PageActionDescriptor actionDescriptor, EndpointMetadataCollection endpointMetadata)
    {
        var viewDescriptor = await Compiler.CompileAsync(actionDescriptor.RelativePath);

        var compiled = _compiledPageActionDescriptorFactory.CreateCompiledDescriptor(actionDescriptor, viewDescriptor);

        var endpoints = new List <Endpoint>();

        _endpointFactory.AddEndpoints(
            endpoints,
            routeNames: new HashSet <string>(StringComparer.OrdinalIgnoreCase),
            action: compiled,
            routes: Array.Empty <ConventionalRouteEntry>(),
            groupConventions: Array.Empty <Action <EndpointBuilder> >(),
            conventions: new Action <EndpointBuilder>[]
        {
            b =>
            {
                // Copy Endpoint metadata for PageActionActionDescriptor to the compiled one.
                // This is particularly important for the runtime compiled scenario where endpoint metadata is added
                // to the PageActionDescriptor, which needs to be accounted for when constructing the
                // CompiledPageActionDescriptor as part of the one of the many matcher policies.
                // Metadata from PageActionDescriptor is less significant than the one discovered from the compiled type.
                // Consequently, we'll insert it at the beginning.
                for (var i = endpointMetadata.Count - 1; i >= 0; i--)
                {
                    b.Metadata.Insert(0, endpointMetadata[i]);
                }
            },
        },
            createInertEndpoints: false);

        // In some test scenarios there's no route so the endpoint isn't created. This is fine because
        // it won't happen for real.
        compiled.Endpoint = endpoints.SingleOrDefault();

        return(compiled);
    }
Example #23
0
        public void OnProvidersExecuting_DoesNotAddAutoValidateAntiforgeryTokenAttribute_IfAntiforgeryPolicyExists()
        {
            // Arrange
            var expected = Mock.Of <IAntiforgeryPolicy>();

            var descriptor = new PageActionDescriptor();
            var provider   = new AutoValidateAntiforgeryPageApplicationModelProvider();
            var context    = new PageApplicationModelProviderContext(descriptor, typeof(object).GetTypeInfo())
            {
                PageApplicationModel = new PageApplicationModel(descriptor, typeof(object).GetTypeInfo(), Array.Empty <object>())
                {
                    Filters = { expected },
                },
            };

            // Act
            provider.OnProvidersExecuting(context);

            // Assert
            Assert.Collection(
                context.PageApplicationModel.Filters,
                actual => Assert.Same(expected, actual));
        }
Example #24
0
        public void OnProvidersExecuting_DiscoversPropertiesFromPage_IfModelTypeDoesNotHaveAttribute()
        {
            // Arrange
            var provider   = CreateProvider();
            var typeInfo   = typeof(PageWithModelWithoutPageModelAttribute).GetTypeInfo();
            var descriptor = new PageActionDescriptor();
            var context    = new PageApplicationModelProviderContext(descriptor, typeInfo);

            // Act
            provider.OnProvidersExecuting(context);

            // Assert
            Assert.NotNull(context.PageApplicationModel);
            var propertiesOnPage = context.PageApplicationModel.HandlerProperties
                                   .Where(p => p.PropertyInfo.DeclaringType.GetTypeInfo() == typeInfo);

            Assert.Collection(
                propertiesOnPage.OrderBy(p => p.PropertyName),
                property =>
            {
                Assert.Equal(typeInfo.GetProperty(nameof(PageWithModelWithoutPageModelAttribute.Model)), property.PropertyInfo);
                Assert.Equal(nameof(PageWithModelWithoutPageModelAttribute.Model), property.PropertyName);
            },
                property =>
            {
                Assert.Equal(typeInfo.GetProperty(nameof(PageWithModelWithoutPageModelAttribute.Property1)), property.PropertyInfo);
                Assert.Null(property.BindingInfo);
                Assert.Equal(nameof(PageWithModelWithoutPageModelAttribute.Property1), property.PropertyName);
            },
                property =>
            {
                Assert.Equal(typeInfo.GetProperty(nameof(PageWithModelWithoutPageModelAttribute.Property2)), property.PropertyInfo);
                Assert.Equal(nameof(PageWithModelWithoutPageModelAttribute.Property2), property.PropertyName);
                Assert.NotNull(property.BindingInfo);
                Assert.Equal(BindingSource.Path, property.BindingInfo.BindingSource);
            });
        }
    public CompiledPageActionDescriptor CreateCompiledDescriptor(
        PageActionDescriptor actionDescriptor,
        CompiledViewDescriptor viewDescriptor)
    {
        var context = new PageApplicationModelProviderContext(actionDescriptor, viewDescriptor.Type !.GetTypeInfo());

        for (var i = 0; i < _applicationModelProviders.Length; i++)
        {
            _applicationModelProviders[i].OnProvidersExecuting(context);
        }

        for (var i = _applicationModelProviders.Length - 1; i >= 0; i--)
        {
            _applicationModelProviders[i].OnProvidersExecuted(context);
        }

        ApplyConventions(_conventions, context.PageApplicationModel);

        var compiled = CompiledPageActionDescriptorBuilder.Build(context.PageApplicationModel, _globalFilters);

        actionDescriptor.CompiledPageDescriptor = compiled;

        return(compiled);
    }
Example #26
0
        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();
        }
Example #27
0
    public override Task <CompiledPageActionDescriptor> LoadAsync(PageActionDescriptor actionDescriptor, EndpointMetadataCollection endpointMetadata)
    {
        if (actionDescriptor == null)
        {
            throw new ArgumentNullException(nameof(actionDescriptor));
        }

        if (actionDescriptor is CompiledPageActionDescriptor compiledPageActionDescriptor)
        {
            // It's possible for some code paths of PageLoaderMatcherPolicy to invoke LoadAsync with an instance
            // of CompiledPageActionDescriptor. In that case, we'll return the instance as-is.
            compiledPageActionDescriptor.CompiledPageActionDescriptorTask ??= Task.FromResult(compiledPageActionDescriptor);
            return(compiledPageActionDescriptor.CompiledPageActionDescriptorTask);
        }

        var task = actionDescriptor.CompiledPageActionDescriptorTask;

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

        return(actionDescriptor.CompiledPageActionDescriptorTask = LoadAsyncCore(actionDescriptor, endpointMetadata));
    }
Example #28
0
        public void OnProvidersExecuting_DiscoversPropertiesFromPageModel_IfModelHasAttribute()
        {
            // Arrange
            var provider   = CreateProvider();
            var typeInfo   = typeof(PageWithModelWithPageModelAttribute).GetTypeInfo();
            var modelType  = typeof(ModelWithPageModelAttribute);
            var descriptor = new PageActionDescriptor();
            var context    = new PageApplicationModelProviderContext(descriptor, typeInfo);

            // Act
            provider.OnProvidersExecuting(context);

            // Assert
            Assert.NotNull(context.PageApplicationModel);
            Assert.Collection(
                context.PageApplicationModel.HandlerProperties.OrderBy(p => p.PropertyName),
                property =>
            {
                Assert.Equal(modelType.GetProperty(nameof(ModelWithPageModelAttribute.Property)), property.PropertyInfo);
                Assert.Equal(nameof(ModelWithPageModelAttribute.Property), property.PropertyName);
                Assert.NotNull(property.BindingInfo);
                Assert.Equal(BindingSource.Path, property.BindingInfo.BindingSource);
            });
        }
    protected override ActionDescriptor CreateActionDescriptor(
        object values,
        string pattern          = null,
        IList <object> metadata = null)
    {
        var action = new PageActionDescriptor();

        foreach (var kvp in new RouteValueDictionary(values))
        {
            action.RouteValues[kvp.Key] = kvp.Value?.ToString();
        }

        if (!string.IsNullOrEmpty(pattern))
        {
            action.AttributeRouteInfo = new AttributeRouteInfo
            {
                Name     = "test",
                Template = pattern,
            };
        }

        action.EndpointMetadata = metadata;
        return(action);
    }
        public Type Load(PageActionDescriptor actionDescriptor)
        {
            var source = CreateSourceDocument(actionDescriptor);

            return(Load(source, actionDescriptor.RelativePath));
        }