Allow serving Razor files with leading underscore

Fixes https://github.com/aspnet/Mvc/issues/8617
This commit is contained in:
Pranav K 2018-10-18 10:15:03 -07:00
parent 27e75e7a51
commit 8a183bb4f4
3 changed files with 71 additions and 43 deletions

View File

@ -57,11 +57,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
{
foreach (var item in _razorFileSystem.EnumerateItems(_pagesOptions.RootDirectory))
{
if (!IsRouteable(item))
{
continue;
}
var relativePath = item.CombinedPath;
if (context.RouteModels.Any(m => string.Equals(relativePath, m.RelativePath, StringComparison.OrdinalIgnoreCase)))
{
@ -99,11 +94,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
{
foreach (var item in _razorFileSystem.EnumerateItems(AreaRootDirectory))
{
if (!IsRouteable(item))
{
continue;
}
var relativePath = item.CombinedPath;
if (context.RouteModels.Any(m => string.Equals(relativePath, m.RelativePath, StringComparison.OrdinalIgnoreCase)))
{
@ -125,11 +115,5 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
}
}
}
private static bool IsRouteable(RazorProjectItem item)
{
// Pages like _ViewImports should not be routeable.
return !item.FileName.StartsWith("_", StringComparison.OrdinalIgnoreCase);
}
}
}

View File

@ -6,7 +6,6 @@ using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
using Microsoft.AspNetCore.Razor.Hosting;
@ -563,6 +562,57 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
});
}
[Fact]
public void OnProvidersExecuting_AllowsRazorFilesWithUnderscorePrefix()
{
// Arrange
var descriptors = new[]
{
CreateVersion_2_1_Descriptor("/Pages/_About.cshtml"),
CreateVersion_2_1_Descriptor("/Pages/Home.cshtml"),
};
var provider = CreateProvider(descriptors: descriptors);
var context = new PageRouteModelProviderContext();
// Act
provider.OnProvidersExecuting(context);
// Assert
Assert.Collection(
context.RouteModels,
result =>
{
Assert.Equal("/Pages/_About.cshtml", result.RelativePath);
Assert.Equal("/_About", result.ViewEnginePath);
Assert.Collection(
result.Selectors,
selector => Assert.Equal("_About", selector.AttributeRouteModel.Template));
Assert.Collection(
result.RouteValues.OrderBy(k => k.Key),
kvp =>
{
Assert.Equal("page", kvp.Key);
Assert.Equal("/_About", kvp.Value);
});
},
result =>
{
Assert.Equal("/Pages/Home.cshtml", result.RelativePath);
Assert.Equal("/Home", result.ViewEnginePath);
Assert.Collection(
result.Selectors,
selector => Assert.Equal("Home", selector.AttributeRouteModel.Template));
Assert.Collection(
result.RouteValues.OrderBy(k => k.Key),
kvp =>
{
Assert.Equal("page", kvp.Key);
Assert.Equal("/Home", kvp.Value);
});
});
}
[Fact]
public void GetRouteTemplate_ReturnsPathFromRazorPageAttribute()
{

View File

@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
fileSystem.Add(new TestRazorProjectItem("/Areas/Products/Pages/Manage/Categories.cshtml", "@page"));
fileSystem.Add(new TestRazorProjectItem("/Areas/Products/Pages/Index.cshtml", "@page"));
fileSystem.Add(new TestRazorProjectItem("/Areas/Products/Pages/List.cshtml", "@page \"{sortOrder?}\""));
fileSystem.Add(new TestRazorProjectItem("/Areas/Products/Pages/_ViewStart.cshtml", "@page"));
fileSystem.Add(new TestRazorProjectItem("/Areas/Products/Pages/_Test.cshtml", "@page"));
var optionsManager = Options.Create(new RazorPagesOptions { AllowAreas = true });
var provider = new RazorProjectPageRouteModelProvider(fileSystem, optionsManager, NullLoggerFactory.Instance);
@ -102,6 +102,24 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
});
},
model =>
{
Assert.Equal("/Areas/Products/Pages/_Test.cshtml", model.RelativePath);
Assert.Equal("/_Test", model.ViewEnginePath);
Assert.Collection(model.Selectors,
selector => Assert.Equal("Products/_Test", selector.AttributeRouteModel.Template));
Assert.Collection(model.RouteValues.OrderBy(k => k.Key),
kvp =>
{
Assert.Equal("area", kvp.Key);
Assert.Equal("Products", kvp.Value);
},
kvp =>
{
Assert.Equal("page", kvp.Key);
Assert.Equal("/_Test", kvp.Value);
});
},
model =>
{
Assert.Equal("/Areas/Products/Pages/Manage/Categories.cshtml", model.RelativePath);
Assert.Equal("/Manage/Categories", model.ViewEnginePath);
@ -272,37 +290,13 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
});
}
[Fact]
public void OnProvidersExecuting_SkipsPagesStartingWithUnderscore()
{
// Arrange
var fileSystem = new VirtualRazorProjectFileSystem();
fileSystem.Add(new TestRazorProjectItem("/Pages/Home.cshtml", "@page"));
fileSystem.Add(new TestRazorProjectItem("/Pages/_Layout.cshtml", "@page"));
var optionsManager = Options.Create(new RazorPagesOptions());
optionsManager.Value.RootDirectory = "/";
var provider = new RazorProjectPageRouteModelProvider(fileSystem, optionsManager, NullLoggerFactory.Instance);
var context = new PageRouteModelProviderContext();
// Act
provider.OnProvidersExecuting(context);
// Assert
Assert.Collection(context.RouteModels,
model =>
{
Assert.Equal("/Pages/Home.cshtml", model.RelativePath);
});
}
[Fact]
public void OnProvidersExecuting_DiscoversFilesUnderBasePath()
{
// Arrange
var fileSystem = new VirtualRazorProjectFileSystem();
fileSystem.Add(new TestRazorProjectItem("/Pages/Index.cshtml", "@page"));
fileSystem.Add(new TestRazorProjectItem("/Pages/_Layout.cshtml", "@page"));
fileSystem.Add(new TestRazorProjectItem("/Pages/_Layout.cshtml", ""));
fileSystem.Add(new TestRazorProjectItem("/NotPages/Index.cshtml", "@page"));
fileSystem.Add(new TestRazorProjectItem("/NotPages/_Layout.cshtml", "@page"));
fileSystem.Add(new TestRazorProjectItem("/Index.cshtml", "@page"));