Fix #6479 - remove IFileProvider constructor

The RazorProject implementation used by MVC at runtime has a constructor
that takes an IFileProvider (used by tests). This causes ambiguities
when a user registers an IFileProvider in DI.

Cleaning up tests to use a mock instead of the file provider directly
This commit is contained in:
Ryan Nowak 2017-07-02 15:38:24 -07:00
parent a23307e2b1
commit 8d9c16132a
9 changed files with 82 additions and 48 deletions

View File

@ -5,7 +5,10 @@ using System.IO;
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Razor.Internal;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@ -17,6 +20,7 @@ namespace MvcSandbox
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSingleton<IFileProvider>(new PhysicalFileProvider(Path.GetFullPath(".")));
services.Insert(0, ServiceDescriptor.Singleton(
typeof(IConfigureOptions<AntiforgeryOptions>),

View File

@ -15,13 +15,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
private readonly IFileProvider _provider;
public FileProviderRazorProject(IRazorViewEngineFileProviderAccessor accessor)
: this(accessor.FileProvider)
{
}
if (accessor == null)
{
throw new ArgumentNullException(nameof(accessor));
}
public FileProviderRazorProject(IFileProvider provider)
{
_provider = provider;
_provider = accessor.FileProvider;
}
public override RazorProjectItem GetItem(string path)

View File

@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Mvc.Razor.Extensions;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using Moq;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Razor.Internal
@ -19,9 +20,12 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
// Arrange
var viewPath = "/Views/Home/Index.cshtml";
var razorEngine = RazorEngine.Create();
var fileProvider = new TestFileProvider();
fileProvider.AddFile(viewPath, "<span name=\"@(User.Id\">");
var razorProject = new FileProviderRazorProject(fileProvider);
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
var razorProject = new FileProviderRazorProject(accessor);
var templateEngine = new MvcRazorTemplateEngine(razorEngine, razorProject);
var codeDocument = templateEngine.CreateCodeDocument(viewPath);
@ -48,13 +52,16 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
// Arrange
var viewPath = "/Views/Home/Index.cshtml";
var physicalPath = @"x:\myapp\views\home\index.cshtml";
var razorEngine = RazorEngine.Create();
var fileProvider = new TestFileProvider();
var file = fileProvider.AddFile(viewPath, "<span name=\"@(User.Id\">");
file.PhysicalPath = physicalPath;
var razorProject = new FileProviderRazorProject(fileProvider);
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
var razorEngine = RazorEngine.Create();
var razorProject = new FileProviderRazorProject(accessor);
var templateEngine = new MvcRazorTemplateEngine(razorEngine, razorProject);
var codeDocument = templateEngine.CreateCodeDocument(viewPath);
// Act
@ -82,9 +89,11 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
var razorEngine = RazorEngine.Create();
var fileProvider = new TestFileProvider();
fileProvider.AddFile(viewPath, fileContent);
var razorProject = new FileProviderRazorProject(fileProvider);
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
var razorProject = new FileProviderRazorProject(accessor);
var templateEngine = new MvcRazorTemplateEngine(razorEngine, razorProject);
var codeDocument = templateEngine.CreateCodeDocument(viewPath);
// Act
@ -105,13 +114,14 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
var fileContent = "@ ";
var importsContent = "@(abc";
var razorEngine = RazorEngine.Create();
var fileProvider = new TestFileProvider();
fileProvider.AddFile(viewPath, fileContent);
var importsFile = fileProvider.AddFile("/Views/_MyImports.cshtml", importsContent);
importsFile.PhysicalPath = importsFilePath;
var razorProject = new FileProviderRazorProject(fileProvider);
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
var razorEngine = RazorEngine.Create();
var razorProject = new FileProviderRazorProject(accessor);
var templateEngine = new MvcRazorTemplateEngine(razorEngine, razorProject)
{
Options =

View File

@ -3,6 +3,7 @@
using System.Linq;
using Microsoft.Extensions.FileProviders;
using Moq;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Razor.Internal
@ -18,7 +19,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
var file2 = fileProvider.AddFile("File2.js", "content");
fileProvider.AddDirectoryContent("/", new IFileInfo[] { file1, file2 });
var razorProject = new FileProviderRazorProject(fileProvider);
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
var razorProject = new FileProviderRazorProject(accessor);
// Act
var razorFiles = razorProject.EnumerateItems("/");
@ -37,7 +40,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
var file3 = fileProvider.AddFile("File3.cshtml", "content");
fileProvider.AddDirectoryContent("/", new IFileInfo[] { file1, file2, file3 });
var razorProject = new FileProviderRazorProject(fileProvider);
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
var razorProject = new FileProviderRazorProject(accessor);
// Act
var razorFiles = razorProject.EnumerateItems("/");
@ -76,7 +81,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
fileProvider.AddDirectoryContent("/Level1-Dir2", new IFileInfo[] { file5 });
fileProvider.AddDirectoryContent("/Level1/Level2", new IFileInfo[0]);
var razorProject = new FileProviderRazorProject(fileProvider);
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
var razorProject = new FileProviderRazorProject(accessor);
// Act
var razorFiles = razorProject.EnumerateItems("/");
@ -117,7 +124,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
fileProvider.AddDirectoryContent("/Level1-Dir2", new IFileInfo[] { file5 });
fileProvider.AddDirectoryContent("/Level1/Level2", new IFileInfo[0]);
var razorProject = new FileProviderRazorProject(fileProvider);
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
var razorProject = new FileProviderRazorProject(accessor);
// Act
var razorFiles = razorProject.EnumerateItems("/Level1-Dir1");

View File

@ -22,15 +22,19 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
$"not be empty. At least one '{typeof(IFileProvider).FullName}' is required to locate a view for " +
"rendering.";
var fileProvider = new NullFileProvider();
var accessor = new Mock<IRazorViewEngineFileProviderAccessor>();
var applicationManager = new ApplicationPartManager();
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
var partManager = new ApplicationPartManager();
var options = new TestOptionsManager<RazorViewEngineOptions>();
var referenceManager = new DefaultRazorReferenceManager(applicationManager, options);
accessor.Setup(a => a.FileProvider).Returns(fileProvider);
var referenceManager = new DefaultRazorReferenceManager(partManager, options);
var provider = new RazorViewCompilerProvider(
applicationManager,
new RazorTemplateEngine(RazorEngine.Create(), new FileProviderRazorProject(fileProvider)),
accessor.Object,
partManager,
new RazorTemplateEngine(
RazorEngine.Create(),
new FileProviderRazorProject(accessor)),
accessor,
new CSharpCompiler(referenceManager, options),
options,
NullLoggerFactory.Instance);

View File

@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.Logging.Abstractions;
using Moq;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Razor.Internal
@ -526,6 +527,8 @@ this should fail";
IList<CompiledViewDescriptor> precompiledViews = null)
{
fileProvider = fileProvider ?? new TestFileProvider();
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
compilationCallback = compilationCallback ?? (_ => { });
var options = new TestOptionsManager<RazorViewEngineOptions>();
if (referenceManager == null)
@ -540,7 +543,7 @@ this should fail";
precompiledViews = precompiledViews ?? Array.Empty<CompiledViewDescriptor>();
var projectSystem = new FileProviderRazorProject(fileProvider);
var projectSystem = new FileProviderRazorProject(accessor);
var templateEngine = new RazorTemplateEngine(RazorEngine.Create(), projectSystem)
{
Options =

View File

@ -934,7 +934,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test
.Returns(GetPageFactoryResult(() => viewStart));
var fileProvider = new TestFileProvider();
var razorProject = new FileProviderRazorProject(fileProvider);
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
var razorProject = new FileProviderRazorProject(accessor);
var viewEngine = CreateViewEngine(pageFactory.Object, razorProject: razorProject);
var context = GetActionContext(_controllerTestContext);
@ -1384,7 +1385,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test
Mock.Of<IRazorPageActivator>(),
new HtmlTestEncoder(),
GetOptionsAccessor(expanders: null),
new FileProviderRazorProject(new TestFileProvider()),
new FileProviderRazorProject(
Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == new TestFileProvider())),
loggerFactory,
new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor"));
@ -1822,7 +1824,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test
pageFactory = pageFactory ?? Mock.Of<IRazorPageFactoryProvider>();
if (razorProject == null)
{
razorProject = new FileProviderRazorProject(new TestFileProvider());
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == new TestFileProvider());
razorProject = new FileProviderRazorProject(accessor);
}
return new TestableRazorViewEngine(pageFactory, GetOptionsAccessor(expanders), razorProject);
}
@ -1923,9 +1926,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test
public TestableRazorViewEngine(
IRazorPageFactoryProvider pageFactory,
IOptions<RazorViewEngineOptions> optionsAccessor)
: this(pageFactory, optionsAccessor, new FileProviderRazorProject(new TestFileProvider()))
{
}
: this(
pageFactory,
optionsAccessor,
new FileProviderRazorProject(
Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == new TestFileProvider())))
{
}
public TestableRazorViewEngine(
IRazorPageFactoryProvider pageFactory,

View File

@ -18,15 +18,13 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
{
// Arrange
var fileProvider = new Mock<IFileProvider>();
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider.Object);
var templateEngine = new RazorTemplateEngine(
RazorEngine.Create(),
new FileProviderRazorProject(fileProvider.Object));
new FileProviderRazorProject(accessor));
var options = new TestOptionsManager<RazorPagesOptions>();
var fileProviderAccessor = new Mock<IRazorViewEngineFileProviderAccessor>();
fileProviderAccessor
.Setup(f => f.FileProvider)
.Returns(fileProvider.Object);
var changeProvider = new PageActionDescriptorChangeProvider(templateEngine, fileProviderAccessor.Object, options);
var changeProvider = new PageActionDescriptorChangeProvider(templateEngine, accessor, options);
// Act
var changeToken = changeProvider.GetChangeToken();
@ -42,16 +40,15 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
{
// Arrange
var fileProvider = new Mock<IFileProvider>();
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider.Object);
var templateEngine = new RazorTemplateEngine(
RazorEngine.Create(),
new FileProviderRazorProject(fileProvider.Object));
new FileProviderRazorProject(accessor));
var options = new TestOptionsManager<RazorPagesOptions>();
options.Value.RootDirectory = rootDirectory;
var fileProviderAccessor = new Mock<IRazorViewEngineFileProviderAccessor>();
fileProviderAccessor
.Setup(f => f.FileProvider)
.Returns(fileProvider.Object);
var changeProvider = new PageActionDescriptorChangeProvider(templateEngine, fileProviderAccessor.Object, options);
var changeProvider = new PageActionDescriptorChangeProvider(templateEngine, accessor, options);
// Act
var changeToken = changeProvider.GetChangeToken();
@ -65,17 +62,16 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
{
// Arrange
var fileProvider = new TestFileProvider();
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
var templateEngine = new RazorTemplateEngine(
RazorEngine.Create(),
new FileProviderRazorProject(fileProvider));
new FileProviderRazorProject(accessor));
templateEngine.Options.ImportsFileName = "_ViewImports.cshtml";
var options = new TestOptionsManager<RazorPagesOptions>();
options.Value.RootDirectory = "/dir1/dir2";
var fileProviderAccessor = new Mock<IRazorViewEngineFileProviderAccessor>();
fileProviderAccessor
.Setup(f => f.FileProvider)
.Returns(fileProvider);
var changeProvider = new PageActionDescriptorChangeProvider(templateEngine, fileProviderAccessor.Object, options);
var changeProvider = new PageActionDescriptorChangeProvider(templateEngine, accessor, options);
// Act & Assert
var compositeChangeToken = Assert.IsType<CompositeChangeToken>(changeProvider.GetChangeToken());

View File

@ -187,8 +187,9 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
var fileProvider = new TestFileProvider();
fileProvider.AddFile("/Home/Path1/_ViewStart.cshtml", "content1");
fileProvider.AddFile("/_ViewStart.cshtml", "content2");
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
var defaultRazorProject = new FileProviderRazorProject(fileProvider);
var defaultRazorProject = new FileProviderRazorProject(accessor);
var invokerProvider = CreateInvokerProvider(
loader.Object,