From aa5a348385a585895bef5b85ac559f4190227601 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 22 Jun 2017 15:29:52 -0700 Subject: [PATCH] _ViewStart.cshtml not picked up when added to the root of the app Fixes #6308 --- .../Internal/PageActionInvokerProvider.cs | 5 +- .../RazorPagesWithBasePathTest.cs | 14 +++ .../Internal/PageActionInvokerProviderTest.cs | 87 +++---------------- .../WithViewStart/ViewStartAtRoot.cshtml | 2 + .../RazorPagesWebSite/_ViewStart.cshtml | 6 ++ 5 files changed, 36 insertions(+), 78 deletions(-) create mode 100644 test/WebSites/RazorPagesWebSite/Pages/WithViewStart/ViewStartAtRoot.cshtml create mode 100644 test/WebSites/RazorPagesWebSite/_ViewStart.cshtml diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/PageActionInvokerProvider.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/PageActionInvokerProvider.cs index 5a2e219384..99b7a7a991 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/PageActionInvokerProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/PageActionInvokerProvider.cs @@ -37,7 +37,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal private readonly IModelMetadataProvider _modelMetadataProvider; private readonly ITempDataDictionaryFactory _tempDataFactory; private readonly HtmlHelperOptions _htmlHelperOptions; - private readonly RazorPagesOptions _razorPagesOptions; private readonly IPageHandlerMethodSelector _selector; private readonly RazorProject _razorProject; private readonly DiagnosticSource _diagnosticSource; @@ -56,7 +55,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal ITempDataDictionaryFactory tempDataFactory, IOptions mvcOptions, IOptions htmlHelperOptions, - IOptions razorPagesOptions, IPageHandlerMethodSelector selector, RazorProject razorProject, DiagnosticSource diagnosticSource, @@ -73,7 +71,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal _modelMetadataProvider = modelMetadataProvider; _tempDataFactory = tempDataFactory; _htmlHelperOptions = htmlHelperOptions.Value; - _razorPagesOptions = razorPagesOptions.Value; _selector = selector; _razorProject = razorProject; _diagnosticSource = diagnosticSource; @@ -210,8 +207,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal internal List> GetViewStartFactories(CompiledPageActionDescriptor descriptor) { var viewStartFactories = new List>(); + // Always pick up all _ViewStarts, including the ones outside the Pages root. var viewStartItems = _razorProject.FindHierarchicalItems( - _razorPagesOptions.RootDirectory, descriptor.RelativePath, ViewStartFileName); foreach (var item in viewStartItems) diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesWithBasePathTest.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesWithBasePathTest.cs index ea6311fa8c..711e221ab3 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesWithBasePathTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesWithBasePathTest.cs @@ -129,6 +129,20 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests Assert.Equal(expected, response.Trim()); } + [Fact] + public async Task ViewStart_IsDiscoveredForFilesOutsidePageRoot() + { + //Arrange + var newLine = Environment.NewLine; + var expected = $"Hello from _ViewStart at root{newLine}Hello from _ViewStart{newLine}Hello from page"; + + // Act + var response = await Client.GetStringAsync("/WithViewStart/ViewStartAtRoot"); + + // Assert + Assert.Equal(expected, response.Trim()); + } + [Fact] public async Task ViewImport_IsDiscoveredWhenRootDirectoryIsSpecified() { diff --git a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PageActionInvokerProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PageActionInvokerProviderTest.cs index eb96379878..aea39e4532 100644 --- a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PageActionInvokerProviderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PageActionInvokerProviderTest.cs @@ -196,8 +196,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal loader.Object, CreateActionDescriptorCollection(descriptor), razorPageFactoryProvider: razorPageFactoryProvider.Object, - razorProject: defaultRazorProject, - razorPagesOptions: new RazorPagesOptions { RootDirectory = "/" }); + razorProject: defaultRazorProject); var context = new ActionInvokerProviderContext(new ActionContext() { @@ -317,67 +316,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal [Fact] public void GetViewStartFactories_FindsFullHeirarchy() { - // Arrange - var descriptor = new PageActionDescriptor() - { - RelativePath = "/Views/Deeper/Index.cshtml", - FilterDescriptors = new FilterDescriptor[0], - ViewEnginePath = "/Views/Deeper/Index.cshtml" - }; - var loader = new Mock(); - loader - .Setup(l => l.Load(It.IsAny())) - .Returns(CreateCompiledPageActionDescriptor(descriptor, typeof(TestPageModel))); - - var fileProvider = new TestFileProvider(); - fileProvider.AddFile("/View/Deeper/Not_ViewStart.cshtml", "page content"); - fileProvider.AddFile("/View/Wrong/_ViewStart.cshtml", "page content"); - fileProvider.AddFile("/_ViewStart.cshtml", "page content "); - fileProvider.AddFile("/Views/_ViewStart.cshtml", "@page starts!"); - fileProvider.AddFile("/Views/Deeper/_ViewStart.cshtml", "page content"); - - var razorProject = new TestRazorProject(fileProvider); - - var mock = new Mock(); - mock - .Setup(p => p.CreateFactory("/Views/Deeper/_ViewStart.cshtml")) - .Returns(new RazorPageFactoryResult(() => null, new List())) - .Verifiable(); - mock - .Setup(p => p.CreateFactory("/Views/_ViewStart.cshtml")) - .Returns(new RazorPageFactoryResult(() => null, new List())) - .Verifiable(); - mock - .Setup(p => p.CreateFactory("/_ViewStart.cshtml")) - .Returns(new RazorPageFactoryResult(() => null, new List())) - .Verifiable(); - - var razorPageFactoryProvider = mock.Object; - - var invokerProvider = CreateInvokerProvider( - loader.Object, - CreateActionDescriptorCollection(descriptor), - pageProvider: null, - modelProvider: null, - razorPageFactoryProvider: razorPageFactoryProvider, - razorProject: razorProject, - razorPagesOptions: new RazorPagesOptions { RootDirectory = "/" }); - - var compiledDescriptor = CreateCompiledPageActionDescriptor(descriptor); - - // Act - var factories = invokerProvider.GetViewStartFactories(compiledDescriptor); - - // Assert - mock.Verify(); - } - - [Theory] - [InlineData("/Pages/Level1/")] - [InlineData("/Pages/Level1")] - public void GetPageFactories_DoesNotFindViewStartsOutsideBaseDirectory(string rootDirectory) - { // Arrange var descriptor = new PageActionDescriptor() { @@ -414,19 +353,22 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal .Setup(p => p.CreateFactory("/Pages/Level1/_ViewStart.cshtml")) .Returns(new RazorPageFactoryResult(() => null, new List())) .Verifiable(); - var razorPageFactoryProvider = mock.Object; + mock + .Setup(p => p.CreateFactory("/Pages/_ViewStart.cshtml")) + .Returns(new RazorPageFactoryResult(() => null, new List())) + .Verifiable(); + mock + .Setup(p => p.CreateFactory("/_ViewStart.cshtml")) + .Returns(new RazorPageFactoryResult(() => null, new List())) + .Verifiable(); - var options = new RazorPagesOptions - { - RootDirectory = rootDirectory, - }; + var razorPageFactoryProvider = mock.Object; var invokerProvider = CreateInvokerProvider( loader.Object, CreateActionDescriptorCollection(descriptor), razorPageFactoryProvider: razorPageFactoryProvider, - razorProject: razorProject, - razorPagesOptions: options); + razorProject: razorProject); // Act var factories = invokerProvider.GetViewStartFactories(compiledPageDescriptor); @@ -474,8 +416,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal pageProvider: null, modelProvider: null, razorPageFactoryProvider: pageFactory.Object, - razorProject: razorProject, - razorPagesOptions: new RazorPagesOptions { RootDirectory = "/" }); + razorProject: razorProject); var compiledDescriptor = CreateCompiledPageActionDescriptor(descriptor); @@ -513,8 +454,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal IPageFactoryProvider pageProvider = null, IPageModelFactoryProvider modelProvider = null, IRazorPageFactoryProvider razorPageFactoryProvider = null, - RazorProject razorProject = null, - RazorPagesOptions razorPagesOptions = null) + RazorProject razorProject = null) { var tempDataFactory = new Mock(); tempDataFactory @@ -544,7 +484,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal tempDataFactory.Object, new TestOptionsManager(), new TestOptionsManager(), - new TestOptionsManager(razorPagesOptions ?? new RazorPagesOptions()), Mock.Of(), razorProject, new DiagnosticListener("Microsoft.AspNetCore"), diff --git a/test/WebSites/RazorPagesWebSite/Pages/WithViewStart/ViewStartAtRoot.cshtml b/test/WebSites/RazorPagesWebSite/Pages/WithViewStart/ViewStartAtRoot.cshtml new file mode 100644 index 0000000000..83faae9562 --- /dev/null +++ b/test/WebSites/RazorPagesWebSite/Pages/WithViewStart/ViewStartAtRoot.cshtml @@ -0,0 +1,2 @@ +@page +Hello from page diff --git a/test/WebSites/RazorPagesWebSite/_ViewStart.cshtml b/test/WebSites/RazorPagesWebSite/_ViewStart.cshtml new file mode 100644 index 0000000000..99606637f8 --- /dev/null +++ b/test/WebSites/RazorPagesWebSite/_ViewStart.cshtml @@ -0,0 +1,6 @@ +@using Microsoft.AspNetCore.Mvc.RazorPages +@if (((PageActionDescriptor)ViewContext.ActionDescriptor).ViewEnginePath == "/WithViewStart/ViewStartAtRoot") +{ +Hello from _ViewStart at root + +} \ No newline at end of file