diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ApplicationParts/AssemblyPart.cs b/src/Microsoft.AspNetCore.Mvc.Core/ApplicationParts/AssemblyPart.cs
index 61ac71bb01..12d251c725 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ApplicationParts/AssemblyPart.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ApplicationParts/AssemblyPart.cs
@@ -4,13 +4,14 @@
using System;
using System.Collections.Generic;
using System.Reflection;
+using Microsoft.Extensions.DependencyModel;
namespace Microsoft.AspNetCore.Mvc.ApplicationParts
{
///
/// An backed by an .
///
- public class AssemblyPart : ApplicationPart, IApplicationPartTypeProvider
+ public class AssemblyPart : ApplicationPart, IApplicationPartTypeProvider, ICompilationLibrariesProvider
{
///
/// Initalizes a new instance.
@@ -38,5 +39,17 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationParts
///
public IEnumerable Types => Assembly.DefinedTypes;
+
+ ///
+ public IReadOnlyList GetCompilationLibraries()
+ {
+ var dependencyContext = DependencyContext.Load(Assembly);
+ if (dependencyContext != null)
+ {
+ return dependencyContext.CompileLibraries;
+ }
+
+ return new CompilationLibrary[0];
+ }
}
}
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ApplicationParts/ICompilationLibrariesProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/ApplicationParts/ICompilationLibrariesProvider.cs
new file mode 100644
index 0000000000..81b28544b2
--- /dev/null
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ApplicationParts/ICompilationLibrariesProvider.cs
@@ -0,0 +1,19 @@
+// 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 System.Collections.Generic;
+using Microsoft.Extensions.DependencyModel;
+
+namespace Microsoft.AspNetCore.Mvc.ApplicationParts
+{
+ ///
+ /// Exposes instances from an .
+ ///
+ public interface ICompilationLibrariesProvider
+ {
+ ///
+ /// Gets the sequence of instances.
+ ///
+ IReadOnlyList GetCompilationLibraries();
+ }
+}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/MetadataReferenceFeature.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/MetadataReferenceFeature.cs
new file mode 100644
index 0000000000..7ad99a2afe
--- /dev/null
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/MetadataReferenceFeature.cs
@@ -0,0 +1,19 @@
+// 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 System.Collections.Generic;
+using Microsoft.CodeAnalysis;
+
+namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
+{
+ ///
+ /// Specifies the list of used in Razor compilation.
+ ///
+ public class MetadataReferenceFeature
+ {
+ ///
+ /// Gets the instances.
+ ///
+ public IList MetadataReferences { get; } = new List();
+ }
+}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/MetadataReferenceFeatureProvider.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/MetadataReferenceFeatureProvider.cs
new file mode 100644
index 0000000000..2651e209fc
--- /dev/null
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/MetadataReferenceFeatureProvider.cs
@@ -0,0 +1,67 @@
+// 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 System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection.PortableExecutable;
+using Microsoft.AspNetCore.Mvc.ApplicationParts;
+using Microsoft.CodeAnalysis;
+using Microsoft.Extensions.DependencyModel;
+
+namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
+{
+ ///
+ /// An for that
+ /// uses for registered instances to create
+ /// .
+ ///
+ public class MetadataReferenceFeatureProvider : IApplicationFeatureProvider
+ {
+ ///
+ public void PopulateFeature(IEnumerable parts, MetadataReferenceFeature feature)
+ {
+ if (parts == null)
+ {
+ throw new ArgumentNullException(nameof(parts));
+ }
+
+ if (feature == null)
+ {
+ throw new ArgumentNullException(nameof(feature));
+ }
+
+ var libraryPaths = new HashSet(StringComparer.OrdinalIgnoreCase);
+ foreach (var providerPart in parts.OfType())
+ {
+ var compileLibraries = providerPart.GetCompilationLibraries();
+
+ for (var i = 0; i < compileLibraries.Count; i++)
+ {
+ var library = compileLibraries[i];
+ var referencePaths = library.ResolveReferencePaths();
+ foreach (var path in referencePaths)
+ {
+ if (libraryPaths.Add(path))
+ {
+ var metadataReference = CreateMetadataReference(path);
+ feature.MetadataReferences.Add(metadataReference);
+ }
+ }
+ }
+ }
+ }
+
+ private static MetadataReference CreateMetadataReference(string path)
+ {
+ using (var stream = File.OpenRead(path))
+ {
+ var moduleMetadata = ModuleMetadata.CreateFromStream(stream, PEStreamOptions.PrefetchMetadata);
+ var assemblyMetadata = AssemblyMetadata.Create(moduleMetadata);
+
+ return assemblyMetadata.GetReference(filePath: path);
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/DependencyInjection/MvcRazorMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNetCore.Mvc.Razor/DependencyInjection/MvcRazorMvcCoreBuilderExtensions.cs
index 484229ac0f..3f8efab48e 100644
--- a/src/Microsoft.AspNetCore.Mvc.Razor/DependencyInjection/MvcRazorMvcCoreBuilderExtensions.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/DependencyInjection/MvcRazorMvcCoreBuilderExtensions.cs
@@ -67,6 +67,11 @@ namespace Microsoft.Extensions.DependencyInjection
{
builder.PartManager.FeatureProviders.Add(new TagHelperFeatureProvider());
}
+
+ if (!builder.PartManager.FeatureProviders.OfType().Any())
+ {
+ builder.PartManager.FeatureProviders.Add(new MetadataReferenceFeatureProvider());
+ }
}
///
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/DefaultRoslynCompilationService.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/DefaultRoslynCompilationService.cs
index b886d11b41..c759f3d92f 100644
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/DefaultRoslynCompilationService.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/DefaultRoslynCompilationService.cs
@@ -7,17 +7,15 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
-using System.Reflection.PortableExecutable;
using System.Text;
using System.Threading;
using Microsoft.AspNetCore.Diagnostics;
-using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Text;
-using Microsoft.Extensions.DependencyModel;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@@ -29,7 +27,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
///
public class DefaultRoslynCompilationService : ICompilationService
{
- private readonly IHostingEnvironment _hostingEnvironment;
+ private readonly ApplicationPartManager _partManager;
private readonly IFileProvider _fileProvider;
private readonly Action _compilationCallback;
private readonly CSharpParseOptions _parseOptions;
@@ -37,22 +35,22 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
private readonly ILogger _logger;
private object _applicationReferencesLock = new object();
private bool _applicationReferencesInitialized;
- private List _applicationReferences;
+ private IList _applicationReferences;
///
/// Initalizes a new instance of the class.
///
- /// The .
+ /// The .
/// Accessor to .
/// The .
/// The .
public DefaultRoslynCompilationService(
- IHostingEnvironment environment,
+ ApplicationPartManager partManager,
IOptions optionsAccessor,
IRazorViewEngineFileProviderAccessor fileProviderAccessor,
ILoggerFactory loggerFactory)
{
- _hostingEnvironment = environment;
+ _partManager = partManager;
_fileProvider = fileProviderAccessor.FileProvider;
_compilationCallback = optionsAccessor.Value.CompilationCallback;
_parseOptions = optionsAccessor.Value.ParseOptions;
@@ -60,7 +58,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
_logger = loggerFactory.CreateLogger();
}
- private List ApplicationReferences
+ private IList ApplicationReferences
{
get
{
@@ -152,19 +150,14 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
}
///
- /// Gets the .
+ /// Gets the sequence of instances used for compilation.
///
- /// The .
- /// The .
- protected virtual DependencyContext GetDependencyContext(IHostingEnvironment hostingEnvironment)
+ /// The instances.
+ protected virtual IList GetApplicationReferences()
{
- if (hostingEnvironment.ApplicationName != null)
- {
- var applicationAssembly = Assembly.Load(new AssemblyName(hostingEnvironment.ApplicationName));
- return DependencyContext.Load(applicationAssembly);
- }
-
- return null;
+ var feature = new MetadataReferenceFeature();
+ _partManager.PopulateFeature(feature);
+ return feature.MetadataReferences;
}
private Assembly LoadStream(MemoryStream assemblyStream, MemoryStream pdbStream)
@@ -240,53 +233,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
return diagnostic.Location.GetMappedLineSpan().Path;
}
- private List GetApplicationReferences()
- {
- var metadataReferences = new List();
- var dependencyContext = GetDependencyContext(_hostingEnvironment);
- if (dependencyContext == null)
- {
- // Avoid null ref if the entry point does not have DependencyContext specified.
- return metadataReferences;
- }
-
- var libraryPaths = new HashSet(StringComparer.OrdinalIgnoreCase);
- for (var i = 0; i < dependencyContext.CompileLibraries.Count; i++)
- {
- var library = dependencyContext.CompileLibraries[i];
- IEnumerable referencePaths;
- try
- {
- referencePaths = library.ResolveReferencePaths();
- }
- catch (InvalidOperationException)
- {
- continue;
- }
-
- foreach (var path in referencePaths)
- {
- if (libraryPaths.Add(path))
- {
- metadataReferences.Add(CreateMetadataFileReference(path));
- }
- }
- }
-
- return metadataReferences;
- }
-
- private MetadataReference CreateMetadataFileReference(string path)
- {
- using (var stream = File.OpenRead(path))
- {
- var moduleMetadata = ModuleMetadata.CreateFromStream(stream, PEStreamOptions.PrefetchMetadata);
- var assemblyMetadata = AssemblyMetadata.Create(moduleMetadata);
-
- return assemblyMetadata.GetReference(filePath: path);
- }
- }
-
private static bool IsError(Diagnostic diagnostic)
{
return diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error;
diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/MetadataReferenceFeatureProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/MetadataReferenceFeatureProviderTest.cs
new file mode 100644
index 0000000000..6ae0f9d964
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/MetadataReferenceFeatureProviderTest.cs
@@ -0,0 +1,68 @@
+// 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 System.Reflection;
+using Microsoft.AspNetCore.Mvc.ApplicationParts;
+using Moq;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
+{
+ public class MetadataReferenceFeatureProviderTest
+ {
+ [Fact]
+ public void PopulateFeature_ReturnsEmptyList_IfNoAssemblyPartsAreRegistered()
+ {
+ // Arrange
+ var applicationPartManager = new ApplicationPartManager();
+ applicationPartManager.ApplicationParts.Add(Mock.Of());
+ applicationPartManager.FeatureProviders.Add(new MetadataReferenceFeatureProvider());
+ var feature = new MetadataReferenceFeature();
+
+ // Act
+ applicationPartManager.PopulateFeature(feature);
+
+ // Assert
+ Assert.Empty(feature.MetadataReferences);
+ }
+
+ [Fact]
+ public void PopulateFeature_ReturnsEmptySequence_IfAssemblyDoesNotPreserveCompilationContext()
+ {
+ // Arrange
+ var applicationPartManager = new ApplicationPartManager();
+ var assemblyPart = new AssemblyPart(typeof(MetadataReferenceFeatureProvider).GetTypeInfo().Assembly);
+ applicationPartManager.ApplicationParts.Add(assemblyPart);
+ applicationPartManager.FeatureProviders.Add(new MetadataReferenceFeatureProvider());
+ var feature = new MetadataReferenceFeature();
+
+ // Act
+ applicationPartManager.PopulateFeature(feature);
+
+ // Assert
+ Assert.Empty(feature.MetadataReferences);
+ }
+
+ [Fact]
+ public void PopulateFeature_AddsMetadataReferenceForAssemblyPartsWithDependencyContext()
+ {
+ // Arrange
+ var applicationPartManager = new ApplicationPartManager();
+ var currentAssembly = GetType().GetTypeInfo().Assembly;
+ var assemblyPart1 = new AssemblyPart(currentAssembly);
+ applicationPartManager.ApplicationParts.Add(assemblyPart1);
+ var assemblyPart2 = new AssemblyPart(typeof(MetadataReferenceFeatureProvider).GetTypeInfo().Assembly);
+ applicationPartManager.ApplicationParts.Add(assemblyPart2);
+ applicationPartManager.FeatureProviders.Add(new MetadataReferenceFeatureProvider());
+ var feature = new MetadataReferenceFeature();
+
+ // Act
+ applicationPartManager.PopulateFeature(feature);
+
+ // Assert
+ Assert.Contains(
+ feature.MetadataReferences,
+ reference => reference.Display.Equals(currentAssembly.Location));
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/DependencyInjection/MvcRazorMvcCoreBuilderExtensionsTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/DependencyInjection/MvcRazorMvcCoreBuilderExtensionsTest.cs
index e57c5828d5..e1aba6824e 100644
--- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/DependencyInjection/MvcRazorMvcCoreBuilderExtensionsTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/DependencyInjection/MvcRazorMvcCoreBuilderExtensionsTest.cs
@@ -6,6 +6,7 @@ using System.Linq;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Internal;
+using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.AspNetCore.Mvc.Razor.Internal;
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Razor.Runtime.TagHelpers;
@@ -55,6 +56,55 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test.DependencyInjection
Assert.Empty(builder.PartManager.ApplicationParts);
}
+ [Fact]
+ public void AddRazorViewEngine_AddsMetadataReferenceFeatureProvider()
+ {
+ // Arrange
+ var services = new ServiceCollection();
+ var builder = services.AddMvcCore();
+
+ // Act
+ builder.AddRazorViewEngine();
+
+ // Assert
+ Assert.Single(builder.PartManager.FeatureProviders.OfType());
+ }
+
+ [Fact]
+ public void AddRazorViewEngine_DoesNotAddMultipleMetadataReferenceFeatureProvider_OnMultipleInvocations()
+ {
+ // Arrange
+ var services = new ServiceCollection();
+ var builder = services.AddMvcCore();
+
+ // Act - 1
+ builder.AddRazorViewEngine();
+
+ // Act - 2
+ builder.AddRazorViewEngine();
+
+ // Assert
+ Assert.Single(builder.PartManager.FeatureProviders.OfType());
+ }
+
+ [Fact]
+ public void AddRazorViewEngine_DoesNotReplaceExistingMetadataReferenceFeatureProvider()
+ {
+ // Arrange
+ var services = new ServiceCollection();
+ var builder = services.AddMvcCore();
+ var metadataReferenceFeatureProvider = new MetadataReferenceFeatureProvider();
+ builder.PartManager.FeatureProviders.Add(metadataReferenceFeatureProvider);
+
+ // Act
+ builder.AddRazorViewEngine();
+
+ // Assert
+ var actual = Assert.Single(
+ builder.PartManager.FeatureProviders.OfType());
+ Assert.Same(metadataReferenceFeatureProvider, actual);
+ }
+
[Fact]
public void AddTagHelpersAsServices_ReplacesTagHelperActivatorAndTagHelperTypeResolver()
{
diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DefaultRoslynCompilationServiceTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DefaultRoslynCompilationServiceTest.cs
index 41abdb501e..cb223a9844 100644
--- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DefaultRoslynCompilationServiceTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DefaultRoslynCompilationServiceTest.cs
@@ -2,13 +2,11 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
-using System.Linq;
using System.Reflection;
-using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
-using Microsoft.Extensions.DependencyModel;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging.Testing;
using Microsoft.Extensions.Options;
@@ -26,10 +24,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
var content = @"
public class MyTestType {}";
- var compilationService = new TestableRoslynCompilationService(
- GetDependencyContext(),
- GetOptions(),
- GetFileProviderAccessor());
+ var compilationService = GetRoslynCompilationService();
var relativeFileInfo = new RelativeFileInfo(
new TestFileInfo { PhysicalPath = "SomePath" },
"some-relative-path");
@@ -53,10 +48,7 @@ this should fail";
var fileProvider = new TestFileProvider();
var fileInfo = fileProvider.AddFile(viewPath, fileContent);
- var compilationService = new TestableRoslynCompilationService(
- GetDependencyContext(),
- GetOptions(),
- GetFileProviderAccessor(fileProvider));
+ var compilationService = GetRoslynCompilationService(fileProvider: fileProvider);
var relativeFileInfo = new RelativeFileInfo(fileInfo, "some-relative-path");
// Act
@@ -77,10 +69,7 @@ this should fail";
var fileContent = "file content";
var content = @"this should fail";
- var compilationService = new TestableRoslynCompilationService(
- GetDependencyContext(),
- GetOptions(),
- GetFileProviderAccessor());
+ var compilationService = GetRoslynCompilationService();
var relativeFileInfo = new RelativeFileInfo(
new TestFileInfo { Content = fileContent },
"some-relative-path");
@@ -112,10 +101,7 @@ this should fail";
var fileProvider = new TestFileProvider();
fileProvider.AddFile(path, mockFileInfo.Object);
- var compilationService = new TestableRoslynCompilationService(
- GetDependencyContext(),
- GetOptions(),
- GetFileProviderAccessor());
+ var compilationService = GetRoslynCompilationService(fileProvider: fileProvider);
var relativeFileInfo = new RelativeFileInfo(mockFileInfo.Object, path);
// Act
@@ -140,14 +126,9 @@ public class MyCustomDefinedClass {}
public class MyNonCustomDefinedClass {}
#endif
";
-
var options = GetOptions();
options.ParseOptions = options.ParseOptions.WithPreprocessorSymbols("MY_CUSTOM_DEFINE");
-
- var compilationService = new TestableRoslynCompilationService(
- GetDependencyContext(),
- options,
- GetFileProviderAccessor());
+ var compilationService = GetRoslynCompilationService(options: options);
var relativeFileInfo = new RelativeFileInfo(
new TestFileInfo { PhysicalPath = "SomePath" },
"some-relative-path");
@@ -170,12 +151,7 @@ public class MyNonCustomDefinedClass {}
fileProvider.AddFile(viewPath, "view-content");
var options = new RazorViewEngineOptions();
options.FileProviders.Add(fileProvider);
-
- var compilationService = new TestableRoslynCompilationService(
- GetDependencyContext(),
- options,
- GetFileProviderAccessor(fileProvider));
-
+ var compilationService = GetRoslynCompilationService(options: options, fileProvider: fileProvider);
var assemblyName = "random-assembly-name";
var diagnostics = new[]
@@ -256,11 +232,8 @@ public class MyNonCustomDefinedClass {}
// Arrange
var content = "public class MyTestType {}";
RoslynCompilationContext usedCompilation = null;
-
- var compilationService = new TestableRoslynCompilationService(
- GetDependencyContext(),
- GetOptions(callback: c => usedCompilation = c),
- GetFileProviderAccessor());
+ var options = GetOptions(c => usedCompilation = c);
+ var compilationService = GetRoslynCompilationService(options: options);
var relativeFileInfo = new RelativeFileInfo(
new TestFileInfo { PhysicalPath = "SomePath" },
@@ -274,43 +247,12 @@ public class MyNonCustomDefinedClass {}
}
[Fact]
- public void Compile_ThrowsIfDependencyContextIsNullAndTheApplicationFailsToCompileWithNoReferences()
+ public void Compile_ThrowsIfNoMetadataReferencesAreDiscoveredAndApplicationFailsToCompile()
{
// Arrange
var content = "public class MyTestType {}";
- var compilationService = new TestableRoslynCompilationService(
- dependencyContext: null,
- viewEngineOptions: GetOptions(),
- fileProviderAccessor: GetFileProviderAccessor());
-
- var relativeFileInfo = new RelativeFileInfo(
- new TestFileInfo { PhysicalPath = "SomePath" },
- "some-relative-path.cshtml");
-
- var expected = "The Razor page 'some-relative-path.cshtml' failed to compile. Ensure that your "
- + "application's project.json sets the 'preserveCompilationContext' compilation property.";
-
- // Act and Assert
- var ex = Assert.Throws(() =>
- compilationService.Compile(relativeFileInfo, content));
- Assert.Equal(expected, ex.Message);
- }
-
- [Fact]
- public void Compile_ThrowsIfDependencyContextReturnsNoReferencesAndTheApplicationFailsToCompile()
- {
- // Arrange
- var content = "public class MyTestType {}";
- var dependencyContext = new DependencyContext(
- new TargetInfo("framework", "runtime", "signature", isPortable: true),
- Extensions.DependencyModel.CompilationOptions.Default,
- new CompilationLibrary[0],
- new RuntimeLibrary[0],
- Enumerable.Empty());
- var compilationService = new TestableRoslynCompilationService(
- dependencyContext: dependencyContext,
- viewEngineOptions: GetOptions(),
- fileProviderAccessor: GetFileProviderAccessor());
+ var applicationPartManager = new ApplicationPartManager();
+ var compilationService = GetRoslynCompilationService(applicationPartManager);
var relativeFileInfo = new RelativeFileInfo(
new TestFileInfo { PhysicalPath = "SomePath" },
@@ -334,11 +276,7 @@ public class MyNonCustomDefinedClass {}
context.Compilation = context.Compilation.RemoveAllReferences();
});
var content = "public class MyTestType {}";
- var compilationService = new TestableRoslynCompilationService(
- dependencyContext: GetDependencyContext(),
- viewEngineOptions: options,
- fileProviderAccessor: GetFileProviderAccessor());
-
+ var compilationService = GetRoslynCompilationService(options: options);
var relativeFileInfo = new RelativeFileInfo(
new TestFileInfo { PhysicalPath = "SomePath" },
"some-relative-path.cshtml");
@@ -363,10 +301,8 @@ public class MyNonCustomDefinedClass {}
.AddReferences(MetadataReference.CreateFromFile(assemblyLocation));
});
var content = "public class MyTestType {}";
- var compilationService = new TestableRoslynCompilationService(
- dependencyContext: null,
- viewEngineOptions: options,
- fileProviderAccessor: GetFileProviderAccessor());
+ var applicationPartManager = new ApplicationPartManager();
+ var compilationService = GetRoslynCompilationService(applicationPartManager, options);
var relativeFileInfo = new RelativeFileInfo(
new TestFileInfo { PhysicalPath = "SomePath" },
@@ -399,7 +335,7 @@ public class MyNonCustomDefinedClass {}
};
}
- private IRazorViewEngineFileProviderAccessor GetFileProviderAccessor(IFileProvider fileProvider = null)
+ private static IRazorViewEngineFileProviderAccessor GetFileProviderAccessor(IFileProvider fileProvider = null)
{
var options = new Mock();
options.SetupGet(o => o.FileProvider)
@@ -408,38 +344,36 @@ public class MyNonCustomDefinedClass {}
return options.Object;
}
- private DependencyContext GetDependencyContext()
+ private static IOptions GetAccessor(RazorViewEngineOptions options)
{
- var assembly = typeof(DefaultRoslynCompilationServiceTest).GetTypeInfo().Assembly;
- return DependencyContext.Load(assembly);
+ var optionsAccessor = new Mock>();
+ optionsAccessor.SetupGet(a => a.Value).Returns(options);
+ return optionsAccessor.Object;
}
- private class TestableRoslynCompilationService : DefaultRoslynCompilationService
+ private static ApplicationPartManager GetApplicationPartManager()
{
- private readonly DependencyContext _dependencyContext;
+ var applicationPartManager = new ApplicationPartManager();
+ var assembly = typeof(DefaultRoslynCompilationServiceTest).GetTypeInfo().Assembly;
+ applicationPartManager.ApplicationParts.Add(new AssemblyPart(assembly));
+ applicationPartManager.FeatureProviders.Add(new MetadataReferenceFeatureProvider());
- public TestableRoslynCompilationService(
- DependencyContext dependencyContext,
- RazorViewEngineOptions viewEngineOptions,
- IRazorViewEngineFileProviderAccessor fileProviderAccessor)
- : base(
- Mock.Of(),
- GetAccessor(viewEngineOptions),
- fileProviderAccessor,
- NullLoggerFactory.Instance)
- {
- _dependencyContext = dependencyContext;
- }
+ return applicationPartManager;
+ }
- private static IOptions GetAccessor(RazorViewEngineOptions options)
- {
- var optionsAccessor = new Mock>();
- optionsAccessor.SetupGet(a => a.Value).Returns(options);
- return optionsAccessor.Object;
- }
+ private static DefaultRoslynCompilationService GetRoslynCompilationService(
+ ApplicationPartManager partManager = null,
+ RazorViewEngineOptions options = null,
+ IFileProvider fileProvider = null)
+ {
+ partManager = partManager ?? GetApplicationPartManager();
+ options = options ?? GetOptions();
- protected override DependencyContext GetDependencyContext(IHostingEnvironment hostingEnvironment)
- => _dependencyContext;
+ return new DefaultRoslynCompilationService(
+ partManager,
+ GetAccessor(options),
+ GetFileProviderAccessor(fileProvider),
+ NullLoggerFactory.Instance);
}
}
}
diff --git a/test/Microsoft.AspNetCore.Mvc.Test/MvcServiceCollectionExtensionsTest.cs b/test/Microsoft.AspNetCore.Mvc.Test/MvcServiceCollectionExtensionsTest.cs
index f0b0ba4906..12bac9568a 100644
--- a/test/Microsoft.AspNetCore.Mvc.Test/MvcServiceCollectionExtensionsTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Test/MvcServiceCollectionExtensionsTest.cs
@@ -18,6 +18,7 @@ using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Formatters.Json.Internal;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Mvc.Razor;
+using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.AspNetCore.Mvc.Razor.Internal;
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Mvc.TagHelpers;
@@ -202,10 +203,11 @@ namespace Microsoft.AspNetCore.Mvc
Assert.NotNull(descriptor.ImplementationInstance);
var manager = Assert.IsType(descriptor.ImplementationInstance);
- Assert.Equal(3, manager.FeatureProviders.Count);
- Assert.IsType(manager.FeatureProviders[0]);
- Assert.IsType(manager.FeatureProviders[1]);
- Assert.IsType(manager.FeatureProviders[2]);
+ Assert.Collection(manager.FeatureProviders,
+ feature => Assert.IsType(feature),
+ feature => Assert.IsType(feature),
+ feature => Assert.IsType(feature),
+ feature => Assert.IsType(feature));
}
[Fact]
diff --git a/test/WebSites/ControllersFromServicesClassLibrary/project.json b/test/WebSites/ControllersFromServicesClassLibrary/project.json
index 224718137b..f6e850ae71 100644
--- a/test/WebSites/ControllersFromServicesClassLibrary/project.json
+++ b/test/WebSites/ControllersFromServicesClassLibrary/project.json
@@ -1,15 +1,18 @@
{
+ "buildOptions": {
+ "preserveCompilationContext": true
+ },
"dependencies": {
"Microsoft.AspNetCore.Mvc": "1.0.0-*"
},
"frameworks": {
- "net451": {},
+ "net451": { },
"netcoreapp1.0": {
"imports": [
"dnxcore50",
"portable-net451+win8"
],
- "dependencies": {}
+ "dependencies": { }
}
}
}
\ No newline at end of file
diff --git a/test/WebSites/ControllersFromServicesWebSite/AssemblyMetadataReferenceFeatureProvider.cs b/test/WebSites/ControllersFromServicesWebSite/AssemblyMetadataReferenceFeatureProvider.cs
new file mode 100644
index 0000000000..99c96ceb38
--- /dev/null
+++ b/test/WebSites/ControllersFromServicesWebSite/AssemblyMetadataReferenceFeatureProvider.cs
@@ -0,0 +1,20 @@
+// 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 System.Collections.Generic;
+using System.Reflection;
+using Microsoft.AspNetCore.Mvc.ApplicationParts;
+using Microsoft.AspNetCore.Mvc.Razor.Compilation;
+using Microsoft.CodeAnalysis;
+
+namespace ControllersFromServicesWebSite
+{
+ public class AssemblyMetadataReferenceFeatureProvider : IApplicationFeatureProvider
+ {
+ public void PopulateFeature(IEnumerable parts, MetadataReferenceFeature feature)
+ {
+ var currentAssembly = GetType().GetTypeInfo().Assembly;
+ feature.MetadataReferences.Add(MetadataReference.CreateFromFile(currentAssembly.Location));
+ }
+ }
+}
diff --git a/test/WebSites/ControllersFromServicesWebSite/Startup.cs b/test/WebSites/ControllersFromServicesWebSite/Startup.cs
index ceb7873090..32441f5a42 100644
--- a/test/WebSites/ControllersFromServicesWebSite/Startup.cs
+++ b/test/WebSites/ControllersFromServicesWebSite/Startup.cs
@@ -25,10 +25,15 @@ namespace ControllersFromServicesWebSite
.AddMvc()
.ConfigureApplicationPartManager(manager => manager.ApplicationParts.Clear())
.AddApplicationPart(typeof(TimeScheduleController).GetTypeInfo().Assembly)
- .ConfigureApplicationPartManager(manager => manager.ApplicationParts.Add(new TypesPart(
- typeof(AnotherController),
- typeof(ComponentFromServicesViewComponent),
- typeof(InServicesTagHelper))))
+ .ConfigureApplicationPartManager(manager =>
+ {
+ manager.ApplicationParts.Add(new TypesPart(
+ typeof(AnotherController),
+ typeof(ComponentFromServicesViewComponent),
+ typeof(InServicesTagHelper)));
+
+ manager.FeatureProviders.Add(new AssemblyMetadataReferenceFeatureProvider());
+ })
.AddControllersAsServices()
.AddViewComponentsAsServices()
.AddTagHelpersAsServices();
diff --git a/test/WebSites/ControllersFromServicesWebSite/project.json b/test/WebSites/ControllersFromServicesWebSite/project.json
index cd61795fce..191edc3064 100644
--- a/test/WebSites/ControllersFromServicesWebSite/project.json
+++ b/test/WebSites/ControllersFromServicesWebSite/project.json
@@ -1,7 +1,6 @@
{
"buildOptions": {
- "emitEntryPoint": true,
- "preserveCompilationContext": true
+ "emitEntryPoint": true
},
"dependencies": {
"Microsoft.NETCore.Platforms": "1.0.1-*",