[Fixes #4550] Add an Option to set the Razor view location formats
This commit is contained in:
parent
1de268d6a7
commit
f7b2ee80fd
|
|
@ -462,6 +462,22 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
return string.Format(CultureInfo.CurrentCulture, GetString("Compilation_DependencyContextIsNotSpecified"), p0, p1, p2);
|
return string.Format(CultureInfo.CurrentCulture, GetString("Compilation_DependencyContextIsNotSpecified"), p0, p1, p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// '{0}' cannot be empty. These locations are required to locate a view for rendering.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewLocationFormatsIsRequired
|
||||||
|
{
|
||||||
|
get { return GetString("ViewLocationFormatsIsRequired"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// '{0}' cannot be empty. These locations are required to locate a view for rendering.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatViewLocationFormatsIsRequired(object p0)
|
||||||
|
{
|
||||||
|
return string.Format(CultureInfo.CurrentCulture, GetString("ViewLocationFormatsIsRequired"), p0);
|
||||||
|
}
|
||||||
|
|
||||||
private static string GetString(string name, params string[] formatterNames)
|
private static string GetString(string name, params string[] formatterNames)
|
||||||
{
|
{
|
||||||
var value = _resourceManager.GetString(name);
|
var value = _resourceManager.GetString(name);
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.Encodings.Web;
|
using System.Text.Encodings.Web;
|
||||||
using Microsoft.AspNetCore.Mvc.Razor.Internal;
|
using Microsoft.AspNetCore.Mvc.Razor.Internal;
|
||||||
using Microsoft.AspNetCore.Mvc.Routing;
|
|
||||||
using Microsoft.AspNetCore.Mvc.ViewEngines;
|
using Microsoft.AspNetCore.Mvc.ViewEngines;
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
@ -21,12 +20,15 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
/// Default implementation of <see cref="IRazorViewEngine"/>.
|
/// Default implementation of <see cref="IRazorViewEngine"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// For <c>ViewResults</c> returned from controllers, views should be located in <see cref="ViewLocationFormats"/>
|
/// For <c>ViewResults</c> returned from controllers, views should be located in
|
||||||
/// by default. For the controllers in an area, views should exist in <see cref="AreaViewLocationFormats"/>.
|
/// <see cref="RazorViewEngineOptions.ViewLocationFormats"/>
|
||||||
|
/// by default. For the controllers in an area, views should exist in
|
||||||
|
/// <see cref="RazorViewEngineOptions.AreaViewLocationFormats"/>.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public class RazorViewEngine : IRazorViewEngine
|
public class RazorViewEngine : IRazorViewEngine
|
||||||
{
|
{
|
||||||
private const string ViewExtension = ".cshtml";
|
public static readonly string ViewExtension = ".cshtml";
|
||||||
|
|
||||||
private const string ControllerKey = "controller";
|
private const string ControllerKey = "controller";
|
||||||
private const string AreaKey = "area";
|
private const string AreaKey = "area";
|
||||||
private static readonly ViewLocationCacheItem[] EmptyViewStartLocationCacheItems =
|
private static readonly ViewLocationCacheItem[] EmptyViewStartLocationCacheItems =
|
||||||
|
|
@ -34,10 +36,10 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
private static readonly TimeSpan _cacheExpirationDuration = TimeSpan.FromMinutes(20);
|
private static readonly TimeSpan _cacheExpirationDuration = TimeSpan.FromMinutes(20);
|
||||||
|
|
||||||
private readonly IRazorPageFactoryProvider _pageFactory;
|
private readonly IRazorPageFactoryProvider _pageFactory;
|
||||||
private readonly IList<IViewLocationExpander> _viewLocationExpanders;
|
|
||||||
private readonly IRazorPageActivator _pageActivator;
|
private readonly IRazorPageActivator _pageActivator;
|
||||||
private readonly HtmlEncoder _htmlEncoder;
|
private readonly HtmlEncoder _htmlEncoder;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
private readonly RazorViewEngineOptions _options;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="RazorViewEngine" />.
|
/// Initializes a new instance of the <see cref="RazorViewEngine" />.
|
||||||
|
|
@ -49,9 +51,24 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
IOptions<RazorViewEngineOptions> optionsAccessor,
|
IOptions<RazorViewEngineOptions> optionsAccessor,
|
||||||
ILoggerFactory loggerFactory)
|
ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
|
_options = optionsAccessor.Value;
|
||||||
|
|
||||||
|
if (_options.ViewLocationFormats.Count == 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(
|
||||||
|
Resources.FormatViewLocationFormatsIsRequired(nameof(RazorViewEngineOptions.ViewLocationFormats)),
|
||||||
|
nameof(optionsAccessor));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_options.AreaViewLocationFormats.Count == 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(
|
||||||
|
Resources.FormatViewLocationFormatsIsRequired(nameof(RazorViewEngineOptions.AreaViewLocationFormats)),
|
||||||
|
nameof(optionsAccessor));
|
||||||
|
}
|
||||||
|
|
||||||
_pageFactory = pageFactory;
|
_pageFactory = pageFactory;
|
||||||
_pageActivator = pageActivator;
|
_pageActivator = pageActivator;
|
||||||
_viewLocationExpanders = optionsAccessor.Value.ViewLocationExpanders;
|
|
||||||
_htmlEncoder = htmlEncoder;
|
_htmlEncoder = htmlEncoder;
|
||||||
_logger = loggerFactory.CreateLogger<RazorViewEngine>();
|
_logger = loggerFactory.CreateLogger<RazorViewEngine>();
|
||||||
ViewLookupCache = new MemoryCache(new MemoryCacheOptions
|
ViewLookupCache = new MemoryCache(new MemoryCacheOptions
|
||||||
|
|
@ -60,47 +77,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the locations where this instance of <see cref="RazorViewEngine"/> will search for views.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// The locations of the views returned from controllers that do not belong to an area.
|
|
||||||
/// Locations are composite format strings (see http://msdn.microsoft.com/en-us/library/txafckwd.aspx),
|
|
||||||
/// which contains following indexes:
|
|
||||||
/// {0} - Action Name
|
|
||||||
/// {1} - Controller Name
|
|
||||||
/// The values for these locations are case-sensitive on case-sensitive file systems.
|
|
||||||
/// For example, the view for the <c>Test</c> action of <c>HomeController</c> should be located at
|
|
||||||
/// <c>/Views/Home/Test.cshtml</c>. Locations such as <c>/views/home/test.cshtml</c> would not be discovered
|
|
||||||
/// </remarks>
|
|
||||||
public virtual IEnumerable<string> ViewLocationFormats { get; } = new[]
|
|
||||||
{
|
|
||||||
"/Views/{1}/{0}" + ViewExtension,
|
|
||||||
"/Views/Shared/{0}" + ViewExtension,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the locations where this instance of <see cref="RazorViewEngine"/> will search for views within an
|
|
||||||
/// area.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// The locations of the views returned from controllers that belong to an area.
|
|
||||||
/// Locations are composite format strings (see http://msdn.microsoft.com/en-us/library/txafckwd.aspx),
|
|
||||||
/// which contains following indexes:
|
|
||||||
/// {0} - Action Name
|
|
||||||
/// {1} - Controller Name
|
|
||||||
/// {2} - Area name
|
|
||||||
/// The values for these locations are case-sensitive on case-sensitive file systems.
|
|
||||||
/// For example, the view for the <c>Test</c> action of <c>HomeController</c> should be located at
|
|
||||||
/// <c>/Views/Home/Test.cshtml</c>. Locations such as <c>/views/home/test.cshtml</c> would not be discovered
|
|
||||||
/// </remarks>
|
|
||||||
public virtual IEnumerable<string> AreaViewLocationFormats { get; } = new[]
|
|
||||||
{
|
|
||||||
"/Areas/{2}/Views/{1}/{0}" + ViewExtension,
|
|
||||||
"/Areas/{2}/Views/Shared/{0}" + ViewExtension,
|
|
||||||
"/Views/Shared/{0}" + ViewExtension,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A cache for results of view lookups.
|
/// A cache for results of view lookups.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -311,15 +287,15 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
isMainPage);
|
isMainPage);
|
||||||
Dictionary<string, string> expanderValues = null;
|
Dictionary<string, string> expanderValues = null;
|
||||||
|
|
||||||
if (_viewLocationExpanders.Count > 0)
|
if (_options.ViewLocationExpanders.Count > 0)
|
||||||
{
|
{
|
||||||
expanderValues = new Dictionary<string, string>(StringComparer.Ordinal);
|
expanderValues = new Dictionary<string, string>(StringComparer.Ordinal);
|
||||||
expanderContext.Values = expanderValues;
|
expanderContext.Values = expanderValues;
|
||||||
|
|
||||||
// Perf: Avoid allocations
|
// Perf: Avoid allocations
|
||||||
for (var i = 0; i < _viewLocationExpanders.Count; i++)
|
for (var i = 0; i < _options.ViewLocationExpanders.Count; i++)
|
||||||
{
|
{
|
||||||
_viewLocationExpanders[i].PopulateValues(expanderContext);
|
_options.ViewLocationExpanders[i].PopulateValues(expanderContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -385,13 +361,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
ViewLocationCacheKey cacheKey)
|
ViewLocationCacheKey cacheKey)
|
||||||
{
|
{
|
||||||
// Only use the area view location formats if we have an area token.
|
// Only use the area view location formats if we have an area token.
|
||||||
var viewLocations = !string.IsNullOrEmpty(expanderContext.AreaName) ?
|
IEnumerable<string> viewLocations = !string.IsNullOrEmpty(expanderContext.AreaName) ?
|
||||||
AreaViewLocationFormats :
|
_options.AreaViewLocationFormats :
|
||||||
ViewLocationFormats;
|
_options.ViewLocationFormats;
|
||||||
|
|
||||||
for (var i = 0; i < _viewLocationExpanders.Count; i++)
|
for (var i = 0; i < _options.ViewLocationExpanders.Count; i++)
|
||||||
{
|
{
|
||||||
viewLocations = _viewLocationExpanders[i].ExpandViewLocations(expanderContext, viewLocations);
|
viewLocations = _options.ViewLocationExpanders[i].ExpandViewLocations(expanderContext, viewLocations);
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewLocationCacheResult cacheResult = null;
|
ViewLocationCacheResult cacheResult = null;
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
private Action<RoslynCompilationContext> _compilationCallback = c => { };
|
private Action<RoslynCompilationContext> _compilationCallback = c => { };
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a <see cref="IList{IViewLocationExpander}"/> used by the <see cref="RazorViewEngine"/>.
|
/// Gets a <see cref="IList{IViewLocationExpander}"/> used by the <see cref="RazorViewEngine"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IList<IViewLocationExpander> ViewLocationExpanders { get; }
|
public IList<IViewLocationExpander> ViewLocationExpanders { get; }
|
||||||
= new List<IViewLocationExpander>();
|
= new List<IViewLocationExpander>();
|
||||||
|
|
@ -35,6 +35,61 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public IList<IFileProvider> FileProviders { get; } = new List<IFileProvider>();
|
public IList<IFileProvider> FileProviders { get; } = new List<IFileProvider>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the locations where <see cref="RazorViewEngine"/> will search for views.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>
|
||||||
|
/// The locations of the views returned from controllers that do not belong to an area.
|
||||||
|
/// Locations are composite format strings (see http://msdn.microsoft.com/en-us/library/txafckwd.aspx),
|
||||||
|
/// which may contain the following format items:
|
||||||
|
/// </para>
|
||||||
|
/// <list type="bullet">
|
||||||
|
/// <item>
|
||||||
|
/// <description>{0} - Action Name</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <description>{1} - Controller Name</description>
|
||||||
|
/// </item>
|
||||||
|
/// </list>
|
||||||
|
/// <para>
|
||||||
|
/// The values for these locations are case-sensitive on case-sensitive file systems.
|
||||||
|
/// For example, the view for the <c>Test</c> action of <c>HomeController</c> should be located at
|
||||||
|
/// <c>/Views/Home/Test.cshtml</c>. Locations such as <c>/views/home/test.cshtml</c> would not be discovered.
|
||||||
|
/// </para>
|
||||||
|
/// </remarks>
|
||||||
|
public IList<string> ViewLocationFormats { get; } = new List<string>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the locations where <see cref="RazorViewEngine"/> will search for views within an
|
||||||
|
/// area.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>
|
||||||
|
/// The locations of the views returned from controllers that belong to an area.
|
||||||
|
/// Locations are composite format strings (see http://msdn.microsoft.com/en-us/library/txafckwd.aspx),
|
||||||
|
/// which may contain the following format items:
|
||||||
|
/// </para>
|
||||||
|
/// <list type="bullet">
|
||||||
|
/// <item>
|
||||||
|
/// <description>{0} - Action Name</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <description>{1} - Controller Name</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <description>{2} - Area Name</description>
|
||||||
|
/// </item>
|
||||||
|
/// </list>
|
||||||
|
/// <para>
|
||||||
|
/// The values for these locations are case-sensitive on case-sensitive file systems.
|
||||||
|
/// For example, the view for the <c>Test</c> action of <c>HomeController</c> under <c>Admin</c> area should
|
||||||
|
/// be located at <c>/Areas/Admin/Views/Home/Test.cshtml</c>.
|
||||||
|
/// Locations such as <c>/areas/admin/views/home/test.cshtml</c> would not be discovered.
|
||||||
|
/// </para>
|
||||||
|
/// </remarks>
|
||||||
|
public IList<string> AreaViewLocationFormats { get; } = new List<string>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the callback that is used to customize Razor compilation
|
/// Gets or sets the callback that is used to customize Razor compilation
|
||||||
/// to change compilation settings you can update <see cref="RoslynCompilationContext.Compilation"/> property.
|
/// to change compilation settings you can update <see cref="RoslynCompilationContext.Compilation"/> property.
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,13 @@ namespace Microsoft.AspNetCore.Mvc
|
||||||
var parseOptions = razorOptions.ParseOptions;
|
var parseOptions = razorOptions.ParseOptions;
|
||||||
razorOptions.ParseOptions = parseOptions.WithPreprocessorSymbols(
|
razorOptions.ParseOptions = parseOptions.WithPreprocessorSymbols(
|
||||||
parseOptions.PreprocessorSymbolNames.Concat(new[] { configurationSymbol }));
|
parseOptions.PreprocessorSymbolNames.Concat(new[] { configurationSymbol }));
|
||||||
|
|
||||||
|
razorOptions.ViewLocationFormats.Add("/Views/{1}/{0}" + RazorViewEngine.ViewExtension);
|
||||||
|
razorOptions.ViewLocationFormats.Add("/Views/Shared/{0}" + RazorViewEngine.ViewExtension);
|
||||||
|
|
||||||
|
razorOptions.AreaViewLocationFormats.Add("/Areas/{2}/Views/{1}/{0}" + RazorViewEngine.ViewExtension);
|
||||||
|
razorOptions.AreaViewLocationFormats.Add("/Areas/{2}/Views/Shared/{0}" + RazorViewEngine.ViewExtension);
|
||||||
|
razorOptions.AreaViewLocationFormats.Add("/Views/Shared/{0}" + RazorViewEngine.ViewExtension);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -203,4 +203,7 @@
|
||||||
<data name="Compilation_DependencyContextIsNotSpecified" xml:space="preserve">
|
<data name="Compilation_DependencyContextIsNotSpecified" xml:space="preserve">
|
||||||
<value>The Razor page '{0}' failed to compile. Ensure that your application's {1} sets the '{2}' compilation property.</value>
|
<value>The Razor page '{0}' failed to compile. Ensure that your application's {1} sets the '{2}' compilation property.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ViewLocationFormatsIsRequired" xml:space="preserve">
|
||||||
|
<value>'{0}' cannot be empty. These locations are required to locate a view for rendering.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
// 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.Linq;
|
||||||
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
||||||
using Microsoft.AspNetCore.Mvc.Internal;
|
using Microsoft.AspNetCore.Mvc.Internal;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
@ -11,6 +13,67 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
{
|
{
|
||||||
public class RazorViewEngineOptionsTest
|
public class RazorViewEngineOptionsTest
|
||||||
{
|
{
|
||||||
|
[Fact]
|
||||||
|
public void AreaViewLocationFormats_ContainsExpectedLocations()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var services = new ServiceCollection().AddOptions();
|
||||||
|
var areaViewLocations = new[]
|
||||||
|
{
|
||||||
|
"/Areas/{2}/MvcViews/{1}/{0}.cshtml",
|
||||||
|
"/Areas/{2}/MvcViews/Shared/{0}.cshtml",
|
||||||
|
"/MvcViews/Shared/{0}.cshtml"
|
||||||
|
};
|
||||||
|
var builder = new MvcBuilder(services, new ApplicationPartManager());
|
||||||
|
builder.AddRazorOptions(options =>
|
||||||
|
{
|
||||||
|
options.AreaViewLocationFormats.Clear();
|
||||||
|
|
||||||
|
foreach (var location in areaViewLocations)
|
||||||
|
{
|
||||||
|
options.AreaViewLocationFormats.Add(location);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var serviceProvider = services.BuildServiceProvider();
|
||||||
|
var accessor = serviceProvider.GetRequiredService<IOptions<RazorViewEngineOptions>>();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var formats = accessor.Value.AreaViewLocationFormats;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(areaViewLocations, formats, StringComparer.Ordinal);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ViewLocationFormats_ContainsExpectedLocations()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var services = new ServiceCollection().AddOptions();
|
||||||
|
var viewLocations = new[]
|
||||||
|
{
|
||||||
|
"/MvcViews/{1}/{0}.cshtml",
|
||||||
|
"/MvcViews/Shared/{0}.cshtml"
|
||||||
|
};
|
||||||
|
var builder = new MvcBuilder(services, new ApplicationPartManager());
|
||||||
|
builder.AddRazorOptions(options =>
|
||||||
|
{
|
||||||
|
options.ViewLocationFormats.Clear();
|
||||||
|
|
||||||
|
foreach (var location in viewLocations)
|
||||||
|
{
|
||||||
|
options.ViewLocationFormats.Add(location);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var serviceProvider = services.BuildServiceProvider();
|
||||||
|
var accessor = serviceProvider.GetRequiredService<IOptions<RazorViewEngineOptions>>();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var formats = accessor.Value.ViewLocationFormats;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(viewLocations, formats, StringComparer.Ordinal);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void AddRazorOptions_ConfiguresOptionsAsExpected()
|
public void AddRazorOptions_ConfiguresOptionsAsExpected()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||||
using Microsoft.AspNetCore.Mvc.Routing;
|
using Microsoft.AspNetCore.Mvc.Routing;
|
||||||
|
|
@ -364,10 +365,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test
|
||||||
.Verifiable();
|
.Verifiable();
|
||||||
var viewEngine = new TestableRazorViewEngine(
|
var viewEngine = new TestableRazorViewEngine(
|
||||||
pageFactory.Object,
|
pageFactory.Object,
|
||||||
GetOptionsAccessor());
|
GetOptionsAccessor(
|
||||||
viewEngine.SetLocationFormats(
|
viewLocationFormats: new[] { "fake-path1/{1}/{0}.rzr" },
|
||||||
new[] { "fake-path1/{1}/{0}.rzr" },
|
areaViewLocationFormats: new[] { "fake-area-path/{2}/{1}/{0}.rzr" }));
|
||||||
new[] { "fake-area-path/{2}/{1}/{0}.rzr" });
|
|
||||||
var context = GetActionContext(_controllerTestContext);
|
var context = GetActionContext(_controllerTestContext);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -393,10 +393,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test
|
||||||
.Verifiable();
|
.Verifiable();
|
||||||
var viewEngine = new TestableRazorViewEngine(
|
var viewEngine = new TestableRazorViewEngine(
|
||||||
pageFactory.Object,
|
pageFactory.Object,
|
||||||
GetOptionsAccessor());
|
GetOptionsAccessor(
|
||||||
viewEngine.SetLocationFormats(
|
viewLocationFormats: new[] { "fake-path1/{1}/{0}.rzr" },
|
||||||
new[] { "fake-path1/{1}/{0}.rzr" },
|
areaViewLocationFormats: new[] { "fake-area-path/{2}/{1}/{0}.rzr" }));
|
||||||
new[] { "fake-area-path/{2}/{1}/{0}.rzr" });
|
|
||||||
var context = GetActionContext(_areaTestContext);
|
var context = GetActionContext(_areaTestContext);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -1462,38 +1461,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test
|
||||||
Assert.Equal(expectedPagePath, result);
|
Assert.Equal(expectedPagePath, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void AreaViewLocationFormats_ContainsExpectedLocations()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var viewEngine = CreateViewEngine();
|
|
||||||
var areaViewLocations = new string[]
|
|
||||||
{
|
|
||||||
"/Areas/{2}/Views/{1}/{0}.cshtml",
|
|
||||||
"/Areas/{2}/Views/Shared/{0}.cshtml",
|
|
||||||
"/Views/Shared/{0}.cshtml"
|
|
||||||
};
|
|
||||||
|
|
||||||
// Act & Assert
|
|
||||||
Assert.Equal(areaViewLocations, viewEngine.AreaViewLocationFormats);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void ViewLocationFormats_ContainsExpectedLocations()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var viewEngine = CreateViewEngine();
|
|
||||||
|
|
||||||
var viewLocations = new string[]
|
|
||||||
{
|
|
||||||
"/Views/{1}/{0}.cshtml",
|
|
||||||
"/Views/Shared/{0}.cshtml"
|
|
||||||
};
|
|
||||||
|
|
||||||
// Act & Assert
|
|
||||||
Assert.Equal(viewLocations, viewEngine.ViewLocationFormats);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetNormalizedRouteValue_ReturnsValueFromRouteValues_IfKeyHandlingIsRequired()
|
public void GetNormalizedRouteValue_ReturnsValueFromRouteValues_IfKeyHandlingIsRequired()
|
||||||
{
|
{
|
||||||
|
|
@ -1713,15 +1680,19 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test
|
||||||
IEnumerable<IViewLocationExpander> expanders = null)
|
IEnumerable<IViewLocationExpander> expanders = null)
|
||||||
{
|
{
|
||||||
pageFactory = pageFactory ?? Mock.Of<IRazorPageFactoryProvider>();
|
pageFactory = pageFactory ?? Mock.Of<IRazorPageFactoryProvider>();
|
||||||
return new TestableRazorViewEngine(
|
return new TestableRazorViewEngine(pageFactory, GetOptionsAccessor(expanders));
|
||||||
pageFactory,
|
|
||||||
GetOptionsAccessor(expanders));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IOptions<RazorViewEngineOptions> GetOptionsAccessor(
|
private static IOptions<RazorViewEngineOptions> GetOptionsAccessor(
|
||||||
IEnumerable<IViewLocationExpander> expanders = null)
|
IEnumerable<IViewLocationExpander> expanders = null,
|
||||||
|
IEnumerable<string> viewLocationFormats = null,
|
||||||
|
IEnumerable<string> areaViewLocationFormats = null)
|
||||||
{
|
{
|
||||||
|
var optionsSetup = new RazorViewEngineOptionsSetup(Mock.Of<IHostingEnvironment>());
|
||||||
|
|
||||||
var options = new RazorViewEngineOptions();
|
var options = new RazorViewEngineOptions();
|
||||||
|
optionsSetup.Configure(options);
|
||||||
|
|
||||||
if (expanders != null)
|
if (expanders != null)
|
||||||
{
|
{
|
||||||
foreach (var expander in expanders)
|
foreach (var expander in expanders)
|
||||||
|
|
@ -1730,6 +1701,26 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (viewLocationFormats != null)
|
||||||
|
{
|
||||||
|
options.ViewLocationFormats.Clear();
|
||||||
|
|
||||||
|
foreach (var location in viewLocationFormats)
|
||||||
|
{
|
||||||
|
options.ViewLocationFormats.Add(location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (areaViewLocationFormats != null)
|
||||||
|
{
|
||||||
|
options.AreaViewLocationFormats.Clear();
|
||||||
|
|
||||||
|
foreach (var location in areaViewLocationFormats)
|
||||||
|
{
|
||||||
|
options.AreaViewLocationFormats.Add(location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var optionsAccessor = new Mock<IOptions<RazorViewEngineOptions>>();
|
var optionsAccessor = new Mock<IOptions<RazorViewEngineOptions>>();
|
||||||
optionsAccessor
|
optionsAccessor
|
||||||
.SetupGet(v => v.Value)
|
.SetupGet(v => v.Value)
|
||||||
|
|
@ -1784,9 +1775,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test
|
||||||
|
|
||||||
private class TestableRazorViewEngine : RazorViewEngine
|
private class TestableRazorViewEngine : RazorViewEngine
|
||||||
{
|
{
|
||||||
private IEnumerable<string> _viewLocationFormats;
|
|
||||||
private IEnumerable<string> _areaViewLocationFormats;
|
|
||||||
|
|
||||||
public TestableRazorViewEngine(
|
public TestableRazorViewEngine(
|
||||||
IRazorPageFactoryProvider pageFactory,
|
IRazorPageFactoryProvider pageFactory,
|
||||||
IOptions<RazorViewEngineOptions> optionsAccessor)
|
IOptions<RazorViewEngineOptions> optionsAccessor)
|
||||||
|
|
@ -1794,20 +1782,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetLocationFormats(
|
|
||||||
IEnumerable<string> viewLocationFormats,
|
|
||||||
IEnumerable<string> areaViewLocationFormats)
|
|
||||||
{
|
|
||||||
_viewLocationFormats = viewLocationFormats;
|
|
||||||
_areaViewLocationFormats = areaViewLocationFormats;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<string> ViewLocationFormats =>
|
|
||||||
_viewLocationFormats != null ? _viewLocationFormats : base.ViewLocationFormats;
|
|
||||||
|
|
||||||
public override IEnumerable<string> AreaViewLocationFormats =>
|
|
||||||
_areaViewLocationFormats != null ? _areaViewLocationFormats : base.AreaViewLocationFormats;
|
|
||||||
|
|
||||||
public IMemoryCache ViewLookupCachePublic => ViewLookupCache;
|
public IMemoryCache ViewLookupCachePublic => ViewLookupCache;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
// 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.IO;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Mvc.Razor;
|
using Microsoft.AspNetCore.Mvc.Razor;
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.Extensions.FileProviders;
|
using Microsoft.Extensions.FileProviders;
|
||||||
using Microsoft.Extensions.PlatformAbstractions;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue