From 49bdcfb150a8ee0cb53ddc07fc3c1a82551c63ba Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Mon, 1 Jan 2018 19:13:43 -0800 Subject: [PATCH] Updated Razor Pages areas for compatibility switches --- .../CompatibilityVersion.cs | 5 +- .../MvcRazorPagesMvcCoreBuilderExtensions.cs | 2 + .../CompiledPageRouteModelProvider.cs | 2 +- .../PageActionDescriptorChangeProvider.cs | 2 +- .../RazorProjectPageRouteModelProvider.cs | 2 +- .../RazorPagesOptions.cs | 56 +++++++++++++++++-- ...gesOptionsConfigureCompatibilityOptions.cs | 35 ++++++++++++ .../CompiledPageRouteModelProviderTest.cs | 4 +- .../PageActionDescriptorChangeProviderTest.cs | 8 +-- .../RazorProjectPageRouteModelProviderTest.cs | 4 +- .../MvcServiceCollectionExtensionsTest.cs | 15 +++++ .../RazorPagesWebSite/StartupWithBasePath.cs | 2 +- 12 files changed, 117 insertions(+), 20 deletions(-) create mode 100644 src/Microsoft.AspNetCore.Mvc.RazorPages/RazorPagesOptionsConfigureCompatibilityOptions.cs diff --git a/src/Microsoft.AspNetCore.Mvc.Core/CompatibilityVersion.cs b/src/Microsoft.AspNetCore.Mvc.Core/CompatibilityVersion.cs index aee3edea86..155ee032d5 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/CompatibilityVersion.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/CompatibilityVersion.cs @@ -51,9 +51,8 @@ namespace Microsoft.AspNetCore.Mvc /// /// ASP.NET Core MVC 2.1 introduces compatibility switches for the following: /// - /// - /// - /// + /// + /// RazorPagesOptions.AllowAreas /// /// Version_2_1, diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/DependencyInjection/MvcRazorPagesMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/DependencyInjection/MvcRazorPagesMvcCoreBuilderExtensions.cs index f4441b8388..7b976eafcd 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/DependencyInjection/MvcRazorPagesMvcCoreBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/DependencyInjection/MvcRazorPagesMvcCoreBuilderExtensions.cs @@ -81,6 +81,8 @@ namespace Microsoft.Extensions.DependencyInjection // Options services.TryAddEnumerable( ServiceDescriptor.Transient, RazorPagesRazorViewEngineOptionsSetup>()); + services.TryAddEnumerable( + ServiceDescriptor.Transient, RazorPagesOptionsConfigureCompatibilityOptions>()); // Action description and invocation services.TryAddEnumerable( diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/CompiledPageRouteModelProvider.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/CompiledPageRouteModelProvider.cs index 509842db97..e4da857964 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/CompiledPageRouteModelProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/CompiledPageRouteModelProvider.cs @@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal { model = GetPageRouteModel(rootDirectory, viewDescriptor); } - else if (_pagesOptions.EnableAreas && viewDescriptor.RelativePath.StartsWith(areaRootDirectory, StringComparison.OrdinalIgnoreCase)) + else if (_pagesOptions.AllowAreas && viewDescriptor.RelativePath.StartsWith(areaRootDirectory, StringComparison.OrdinalIgnoreCase)) { model = GetAreaPageRouteModel(areaRootDirectory, viewDescriptor); } diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/PageActionDescriptorChangeProvider.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/PageActionDescriptorChangeProvider.cs index 0e9f653b11..3d70ff68cc 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/PageActionDescriptorChangeProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/PageActionDescriptorChangeProvider.cs @@ -56,7 +56,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal var additionalImportFilePaths = templateEngine.GetImportItems(importFileAtPagesRoot) .Select(item => item.FilePath); - if (razorPagesOptions.Value.EnableAreas) + if (razorPagesOptions.Value.AllowAreas) { var areaRootDirectory = razorPagesOptions.Value.AreaRootDirectory; Debug.Assert(!string.IsNullOrEmpty(areaRootDirectory)); diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/RazorProjectPageRouteModelProvider.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/RazorProjectPageRouteModelProvider.cs index 3be91f26d2..a2f0c8cf2d 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/RazorProjectPageRouteModelProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/RazorProjectPageRouteModelProvider.cs @@ -39,7 +39,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal { AddPageModels(context); - if (_pagesOptions.EnableAreas) + if (_pagesOptions.AllowAreas) { AddAreaPageModels(context); } diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/RazorPagesOptions.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/RazorPagesOptions.cs index bb013f5246..ac19b3c208 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/RazorPagesOptions.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/RazorPagesOptions.cs @@ -2,18 +2,34 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections; +using System.Collections.Generic; using Microsoft.AspNetCore.Mvc.ApplicationModels; +using Microsoft.AspNetCore.Mvc.Infrastructure; namespace Microsoft.AspNetCore.Mvc.RazorPages { /// /// Provides configuration for RazorPages. /// - public class RazorPagesOptions + public class RazorPagesOptions : IEnumerable { + private readonly CompatibilitySwitch _allowAreas; + private readonly ICompatibilitySwitch[] _switches; + private string _root = "/Pages"; private string _areasRoot = "/Areas"; + public RazorPagesOptions() + { + _allowAreas = new CompatibilitySwitch(nameof(AllowAreas)); + + _switches = new ICompatibilitySwitch[] + { + _allowAreas, + }; + } + /// /// Gets a collection of instances that are applied during /// route and page model construction. @@ -45,20 +61,43 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// /// Gets or sets a value that determines if areas are enabled for Razor Pages. - /// Defaults to true. + /// Defaults to false. + /// + /// /// /// When enabled, any Razor Page under the directory structure /{AreaRootDirectory}/AreaName/{RootDirectory}/ /// will be associated with an area with the name AreaName. /// /// /// - /// - public bool EnableAreas { get; set; } + /// + /// This property is associated with a compatibility switch and can provide a different behavior depending on + /// the configured compatibility version for the application. See for + /// guidance and examples of setting the application's compatibility version. + /// + /// + /// Configuring the desired of the value compatibility switch by calling this property's setter will take precedence + /// over the value implied by the application's . + /// + /// + /// If the application's compatibility version is set to then + /// this setting will have value false if not explicitly configured. + /// + /// + /// If the application's compatibility version is set to or + /// higher then this setting will have value true if not explicitly configured. + /// + /// + public bool AllowAreas + { + get => _allowAreas.Value; + set => _allowAreas.Value = value; + } /// /// Application relative path used as the root of discovery for Razor Page files associated with areas. /// Defaults to the /Areas directory under application root. - /// + /// /// public string AreaRootDirectory { @@ -78,5 +117,12 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages _areasRoot = value; } } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)_switches).GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() => _switches.GetEnumerator(); } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/RazorPagesOptionsConfigureCompatibilityOptions.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/RazorPagesOptionsConfigureCompatibilityOptions.cs new file mode 100644 index 0000000000..ddc8d77a93 --- /dev/null +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/RazorPagesOptionsConfigureCompatibilityOptions.cs @@ -0,0 +1,35 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc.Infrastructure; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Microsoft.AspNetCore.Mvc.RazorPages +{ + internal class RazorPagesOptionsConfigureCompatibilityOptions : ConfigureCompatibilityOptions + { + public RazorPagesOptionsConfigureCompatibilityOptions( + ILoggerFactory loggerFactory, + IOptions compatibilityOptions) + : base(loggerFactory, compatibilityOptions) + { + } + + protected override IReadOnlyDictionary DefaultValues + { + get + { + var values = new Dictionary(); + + if (Version >= CompatibilityVersion.Version_2_1) + { + values[nameof(RazorPagesOptions.AllowAreas)] = true; + } + + return values; + } + } + } +} diff --git a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/CompiledPageRouteModelProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/CompiledPageRouteModelProviderTest.cs index 3b4e4c7928..be8e08e304 100644 --- a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/CompiledPageRouteModelProviderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/CompiledPageRouteModelProviderTest.cs @@ -73,7 +73,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal }; var options = new RazorPagesOptions { - EnableAreas = true, + AllowAreas = true, AreaRootDirectory = "/Features", RootDirectory = "/Files", }; @@ -151,7 +151,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal GetDescriptor("/Pages/About.cshtml"), GetDescriptor("/Areas/Accounts/Pages/Home.cshtml"), }; - var options = new RazorPagesOptions { EnableAreas = false }; + var options = new RazorPagesOptions { AllowAreas = false }; var provider = new TestCompiledPageRouteModelProvider(descriptors, options); var context = new PageRouteModelProviderContext(); diff --git a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PageActionDescriptorChangeProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PageActionDescriptorChangeProviderTest.cs index 21d7e6fa09..961b333e28 100644 --- a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PageActionDescriptorChangeProviderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PageActionDescriptorChangeProviderTest.cs @@ -74,7 +74,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal var templateEngine = new RazorTemplateEngine( RazorEngine.Create(), new FileProviderRazorProject(accessor)); - var options = Options.Create(new RazorPagesOptions { EnableAreas = true }); + var options = Options.Create(new RazorPagesOptions { AllowAreas = true }); var changeProvider = new PageActionDescriptorChangeProvider(templateEngine, accessor, options); // Act @@ -100,7 +100,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal new FileProviderRazorProject(accessor)); var options = Options.Create(new RazorPagesOptions { - EnableAreas = true, + AllowAreas = true, AreaRootDirectory = rootDirectory, }); var changeProvider = new PageActionDescriptorChangeProvider(templateEngine, accessor, options); @@ -150,7 +150,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal var options = Options.Create(new RazorPagesOptions()); options.Value.RootDirectory = "/dir1/dir2"; options.Value.AreaRootDirectory = "/dir3/dir4"; - options.Value.EnableAreas = true; + options.Value.AllowAreas = true; var changeProvider = new PageActionDescriptorChangeProvider(templateEngine, accessor, options); @@ -175,7 +175,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal RazorEngine.Create(), new FileProviderRazorProject(accessor)); templateEngine.Options.ImportsFileName = "_ViewImports.cshtml"; - var options = Options.Create(new RazorPagesOptions { EnableAreas = false }); + var options = Options.Create(new RazorPagesOptions { AllowAreas = false }); var changeProvider = new PageActionDescriptorChangeProvider(templateEngine, accessor, options); diff --git a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/RazorProjectPageRouteModelProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/RazorProjectPageRouteModelProviderTest.cs index ff262a8d71..11bea486d7 100644 --- a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/RazorProjectPageRouteModelProviderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/RazorProjectPageRouteModelProviderTest.cs @@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal var project = new TestRazorProject(fileProvider); - var optionsManager = Options.Create(new RazorPagesOptions { EnableAreas = true }); + var optionsManager = Options.Create(new RazorPagesOptions { AllowAreas = true }); var provider = new RazorProjectPageRouteModelProvider(project, optionsManager, NullLoggerFactory.Instance); var context = new PageRouteModelProviderContext(); @@ -153,7 +153,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal var project = new TestRazorProject(fileProvider); - var optionsManager = Options.Create(new RazorPagesOptions { EnableAreas = false }); + var optionsManager = Options.Create(new RazorPagesOptions { AllowAreas = false }); var provider = new RazorProjectPageRouteModelProvider(project, optionsManager, NullLoggerFactory.Instance); var context = new PageRouteModelProviderContext(); diff --git a/test/Microsoft.AspNetCore.Mvc.Test/MvcServiceCollectionExtensionsTest.cs b/test/Microsoft.AspNetCore.Mvc.Test/MvcServiceCollectionExtensionsTest.cs index 87a3a1b95a..b4fdbfc7b7 100644 --- a/test/Microsoft.AspNetCore.Mvc.Test/MvcServiceCollectionExtensionsTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Test/MvcServiceCollectionExtensionsTest.cs @@ -23,6 +23,7 @@ using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.AspNetCore.Mvc.Razor.Compilation; using Microsoft.AspNetCore.Mvc.Razor.Internal; using Microsoft.AspNetCore.Mvc.Razor.TagHelpers; +using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure; using Microsoft.AspNetCore.Mvc.RazorPages.Internal; using Microsoft.AspNetCore.Mvc.TagHelpers; @@ -371,6 +372,20 @@ namespace Microsoft.AspNetCore.Mvc typeof(RazorPagesRazorViewEngineOptionsSetup), } }, + { + typeof(IPostConfigureOptions), + new[] + { + typeof(MvcOptions).Assembly.GetType("Microsoft.AspNetCore.Mvc.Infrastructure.MvcOptionsConfigureCompatibilityOptions", throwOnError: true), + } + }, + { + typeof(IPostConfigureOptions), + new[] + { + typeof(RazorPagesOptions).Assembly.GetType("Microsoft.AspNetCore.Mvc.RazorPages.RazorPagesOptionsConfigureCompatibilityOptions", throwOnError: true), + } + }, { typeof(IActionConstraintProvider), new Type[] diff --git a/test/WebSites/RazorPagesWebSite/StartupWithBasePath.cs b/test/WebSites/RazorPagesWebSite/StartupWithBasePath.cs index 9bf43aff50..549cf8c69f 100644 --- a/test/WebSites/RazorPagesWebSite/StartupWithBasePath.cs +++ b/test/WebSites/RazorPagesWebSite/StartupWithBasePath.cs @@ -17,7 +17,7 @@ namespace RazorPagesWebSite .AddCookieTempDataProvider() .AddRazorPagesOptions(options => { - options.EnableAreas = true; + options.AllowAreas = true; options.Conventions.AuthorizePage("/Conventions/Auth"); options.Conventions.AuthorizeFolder("/Conventions/AuthFolder"); });