Update default Razor search paths to include ~/[PagesRoot]/Shared

Fixes #6604
This commit is contained in:
Pranav K 2017-09-07 12:51:38 -07:00
parent a8b7904b00
commit 6bf165f22f
14 changed files with 208 additions and 11 deletions

View File

@ -113,6 +113,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor
/// /Pages/Account/{0}.cshtml /// /Pages/Account/{0}.cshtml
/// /Pages/{0}.cshtml /// /Pages/{0}.cshtml
/// /Views/Shared/{0}.cshtml /// /Views/Shared/{0}.cshtml
/// /Pages/Shared/{0}.cshtml
/// </para> /// </para>
/// </remarks> /// </remarks>
public IList<string> PageViewLocationFormats { get; } = new List<string>(); public IList<string> PageViewLocationFormats { get; } = new List<string>();

View File

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Diagnostics; using System.Diagnostics;
using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure; using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
@ -10,29 +11,45 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
{ {
public class RazorPagesRazorViewEngineOptionsSetup : IConfigureOptions<RazorViewEngineOptions> public class RazorPagesRazorViewEngineOptionsSetup : IConfigureOptions<RazorViewEngineOptions>
{ {
private readonly IOptions<RazorPagesOptions> _pagesOptions; private readonly RazorPagesOptions _pagesOptions;
public RazorPagesRazorViewEngineOptionsSetup(IOptions<RazorPagesOptions> pagesOptions) public RazorPagesRazorViewEngineOptionsSetup(IOptions<RazorPagesOptions> pagesOptions)
{ {
_pagesOptions = pagesOptions; _pagesOptions = pagesOptions?.Value ?? throw new ArgumentNullException(nameof(pagesOptions));
} }
public void Configure(RazorViewEngineOptions options) public void Configure(RazorViewEngineOptions options)
{ {
Debug.Assert(_pagesOptions.Value.RootDirectory.Length > 0); if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
if (_pagesOptions.Value.RootDirectory == "/") var rootDirectory = _pagesOptions.RootDirectory;
{ Debug.Assert(!string.IsNullOrEmpty(rootDirectory));
options.PageViewLocationFormats.Add("/{1}/{0}" + RazorViewEngine.ViewExtension); var defaultPageSearchPath = CombinePath(rootDirectory, "{1}/{0}");
} options.PageViewLocationFormats.Add(defaultPageSearchPath);
else
{ // /Pages/Shared/{0}.cshtml
options.PageViewLocationFormats.Add(_pagesOptions.Value.RootDirectory + "/{1}/{0}" + RazorViewEngine.ViewExtension); var pagesSharedDirectory = CombinePath(rootDirectory, "Shared/{0}");
} options.PageViewLocationFormats.Add(pagesSharedDirectory);
options.PageViewLocationFormats.Add("/Views/Shared/{0}" + RazorViewEngine.ViewExtension); options.PageViewLocationFormats.Add("/Views/Shared/{0}" + RazorViewEngine.ViewExtension);
options.ViewLocationFormats.Add(pagesSharedDirectory);
options.AreaViewLocationFormats.Add(pagesSharedDirectory);
options.ViewLocationExpanders.Add(new PageViewLocationExpander()); options.ViewLocationExpanders.Add(new PageViewLocationExpander());
} }
private static string CombinePath(string path1, string path2)
{
if (path1.EndsWith("/", StringComparison.Ordinal))
{
return path1 + path2 + RazorViewEngine.ViewExtension;
}
return path1 + "/" + path2 + RazorViewEngine.ViewExtension;
}
} }
} }

View File

@ -274,5 +274,18 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
// Assert // Assert
Assert.Equal(expected, response.Trim()); Assert.Equal(expected, response.Trim());
} }
[Fact]
public async Task Pages_ReturnsFromPagesSharedDirectory()
{
// Arrange
var expected = "Hello from Pages/Shared";
// Act
var response = await Client.GetStringAsync("/SearchInPages");
// Assert
Assert.Equal(expected, response.Trim());
}
} }
} }

View File

@ -513,5 +513,18 @@ Partial";
// Assert // Assert
Assert.Equal(expected, responseContent.Trim()); Assert.Equal(expected, responseContent.Trim());
} }
[Fact]
public async Task ViewEngine_DiscoversViewsFromPagesSharedDirectory()
{
// Arrange
var expected = "Hello from Pages/Shared";
// Act
var responseContent = await Client.GetStringAsync("/ViewEngine/SearchInPages");
// Assert
Assert.Equal(expected, responseContent.Trim());
}
} }
} }

View File

@ -1990,6 +1990,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor
var options = new RazorViewEngineOptions(); var options = new RazorViewEngineOptions();
optionsSetup.Configure(options); optionsSetup.Configure(options);
options.PageViewLocationFormats.Add("/Views/Shared/{0}.cshtml"); options.PageViewLocationFormats.Add("/Views/Shared/{0}.cshtml");
options.PageViewLocationFormats.Add("/Pages/Shared/{0}.cshtml");
if (expanders != null) if (expanders != null)
{ {

View File

@ -0,0 +1,142 @@
// 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 Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Razor.Internal;
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
using Moq;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
{
public class RazorPagesRazorViewEngineOptionsSetupTest
{
[Fact]
public void Configure_AddsPageViewLocationFormats_WhenPagesRootIsAppRoot()
{
// Arrange
var expected = new[]
{
"/{1}/{0}.cshtml",
"/Shared/{0}.cshtml",
"/Views/Shared/{0}.cshtml",
};
var razorPagesOptions = new RazorPagesOptions
{
RootDirectory = "/"
};
var viewEngineOptions = GetViewEngineOptions();
var setup = new RazorPagesRazorViewEngineOptionsSetup(
new TestOptionsManager<RazorPagesOptions>(razorPagesOptions));
// Act
setup.Configure(viewEngineOptions);
// Assert
Assert.Equal(expected, viewEngineOptions.PageViewLocationFormats);
}
[Fact]
public void Configure_AddsPageViewLocationFormats_WithDefaultPagesRoot()
{
// Arrange
var expected = new[]
{
"/Pages/{1}/{0}.cshtml",
"/Pages/Shared/{0}.cshtml",
"/Views/Shared/{0}.cshtml",
};
var razorPagesOptions = new RazorPagesOptions();
var viewEngineOptions = GetViewEngineOptions();
var setup = new RazorPagesRazorViewEngineOptionsSetup(
new TestOptionsManager<RazorPagesOptions>(razorPagesOptions));
// Act
setup.Configure(viewEngineOptions);
// Assert
Assert.Equal(expected, viewEngineOptions.PageViewLocationFormats);
}
[Fact]
public void Configure_AddsSharedPagesDirectoryToViewLocationFormats()
{
// Arrange
var expected = new[]
{
"/Views/{1}/{0}.cshtml",
"/Views/Shared/{0}.cshtml",
"/PagesRoot/Shared/{0}.cshtml",
};
var razorPagesOptions = new RazorPagesOptions
{
RootDirectory = "/PagesRoot",
};
var viewEngineOptions = GetViewEngineOptions();
var setup = new RazorPagesRazorViewEngineOptionsSetup(
new TestOptionsManager<RazorPagesOptions>(razorPagesOptions));
// Act
setup.Configure(viewEngineOptions);
// Assert
Assert.Equal(expected, viewEngineOptions.ViewLocationFormats);
}
[Fact]
public void Configure_AddsSharedPagesDirectoryToAreaViewLocationFormats()
{
// Arrange
var expected = new[]
{
"/Areas/{2}/Views/{1}/{0}.cshtml",
"/Areas/{2}/Views/Shared/{0}.cshtml",
"/Views/Shared/{0}.cshtml",
"/PagesRoot/Shared/{0}.cshtml",
};
var razorPagesOptions = new RazorPagesOptions
{
RootDirectory = "/PagesRoot",
};
var viewEngineOptions = GetViewEngineOptions();
var setup = new RazorPagesRazorViewEngineOptionsSetup(
new TestOptionsManager<RazorPagesOptions>(razorPagesOptions));
// Act
setup.Configure(viewEngineOptions);
// Assert
Assert.Equal(expected, viewEngineOptions.AreaViewLocationFormats);
}
[Fact]
public void Configure_RegistersPageViewLocationExpander()
{
// Arrange
var viewEngineOptions = GetViewEngineOptions();
var setup = new RazorPagesRazorViewEngineOptionsSetup(new TestOptionsManager<RazorPagesOptions>());
// Act
setup.Configure(viewEngineOptions);
// Assert
Assert.Collection(
viewEngineOptions.ViewLocationExpanders,
expander => Assert.IsType<PageViewLocationExpander>(expander));
}
private static RazorViewEngineOptions GetViewEngineOptions()
{
var defaultSetup = new RazorViewEngineOptionsSetup(Mock.Of<IHostingEnvironment>());
var options = new RazorViewEngineOptions();
defaultSetup.Configure(options);
return options;
}
}
}

View File

@ -0,0 +1 @@
@Html.Partial("_FileInShared)

View File

@ -0,0 +1,2 @@
@page
@Html.Partial("_FileInShared")

View File

@ -0,0 +1 @@
Hello from Pages/Shared

View File

@ -0,0 +1 @@
@{ throw new Exception("This file should not be processed"); }

View File

@ -77,5 +77,7 @@ namespace RazorWebSite.Controllers
{ {
return View(); return View();
} }
public IActionResult SearchInPages() => View();
} }
} }

View File

@ -0,0 +1 @@
@{ throw new Exception("This file should not be processed"); }

View File

@ -0,0 +1 @@
Hello from Pages/Shared

View File

@ -0,0 +1 @@
@Html.Partial("_SharedFromPages")