diff --git a/src/Microsoft.AspNet.Mvc.Razor/Compilation/CompilationOptionsProviderExtension.cs b/src/Microsoft.AspNet.Mvc.Razor/Compilation/CompilationOptionsProviderExtension.cs
new file mode 100644
index 0000000000..4e0ccc6179
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Razor/Compilation/CompilationOptionsProviderExtension.cs
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using Microsoft.Framework.Runtime;
+using Microsoft.Framework.Runtime.Roslyn;
+
+namespace Microsoft.AspNet.Mvc.Razor
+{
+ ///
+ /// Extension methods for .
+ ///
+ public static class CompilationOptionsProviderExtension
+ {
+ ///
+ /// Parses the for the current executing application and returns a
+ /// used for Roslyn compilation.
+ ///
+ /// A that reads compiler options.
+ /// The for the executing application.
+ /// The for the current application.
+ public static CompilationSettings GetCompilationSettings(
+ [NotNull] this ICompilerOptionsProvider compilerOptionsProvider,
+ [NotNull] IApplicationEnvironment applicationEnvironment)
+ {
+ return compilerOptionsProvider.GetCompilerOptions(applicationEnvironment.ApplicationBasePath,
+ applicationEnvironment.RuntimeFramework,
+ applicationEnvironment.Configuration)
+ .ToCompilationSettings(applicationEnvironment.RuntimeFramework);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Razor/Compilation/RoslynCompilationService.cs b/src/Microsoft.AspNet.Mvc.Razor/Compilation/RoslynCompilationService.cs
index a0a977e037..047ce5acb3 100644
--- a/src/Microsoft.AspNet.Mvc.Razor/Compilation/RoslynCompilationService.cs
+++ b/src/Microsoft.AspNet.Mvc.Razor/Compilation/RoslynCompilationService.cs
@@ -15,7 +15,7 @@ using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.Framework.Runtime;
-namespace Microsoft.AspNet.Mvc.Razor.Compilation
+namespace Microsoft.AspNet.Mvc.Razor
{
///
/// A type that uses Roslyn to compile C# content.
@@ -29,6 +29,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
private readonly ILibraryManager _libraryManager;
private readonly IApplicationEnvironment _environment;
private readonly IAssemblyLoadContext _loader;
+ private readonly ICompilerOptionsProvider _compilerOptionsProvider;
private readonly Lazy> _applicationReferences;
@@ -44,12 +45,14 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
public RoslynCompilationService(IApplicationEnvironment environment,
IAssemblyLoadContextAccessor loaderAccessor,
ILibraryManager libraryManager,
+ ICompilerOptionsProvider compilerOptionsProvider,
IMvcRazorHost host)
{
_environment = environment;
_loader = loaderAccessor.GetLoadContext(typeof(RoslynCompilationService).GetTypeInfo().Assembly);
_libraryManager = libraryManager;
_applicationReferences = new Lazy>(GetApplicationReferences);
+ _compilerOptionsProvider = compilerOptionsProvider;
_classPrefix = host.MainClassNamePrefix;
}
@@ -60,15 +63,19 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
// map to the source file. If a file does not exist on a physical file system, PhysicalPath will be null.
// This prevents files that exist in a non-physical file system from being debugged.
var path = fileInfo.PhysicalPath ?? fileInfo.Name;
- var syntaxTrees = new[] { SyntaxTreeGenerator.Generate(compilationContent, path) };
-
+ var compilationSettings = _compilerOptionsProvider.GetCompilationSettings(_environment);
+ var syntaxTree = SyntaxTreeGenerator.Generate(compilationContent,
+ path,
+ compilationSettings);
var references = _applicationReferences.Value;
var assemblyName = Path.GetRandomFileName();
+ var compilationOptions = compilationSettings.CompilationOptions
+ .WithOutputKind(OutputKind.DynamicallyLinkedLibrary);
var compilation = CSharpCompilation.Create(assemblyName,
- options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
- syntaxTrees: syntaxTrees,
+ options: compilationOptions,
+ syntaxTrees: new[] { syntaxTree },
references: references);
using (var ms = new MemoryStream())
@@ -115,7 +122,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
.First(t => t.Name.
StartsWith(_classPrefix, StringComparison.Ordinal));
- return UncachedCompilationResult.Successful(type);
+ return UncachedCompilationResult.Successful(type, compilationContent);
}
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Razor/Compilation/SyntaxTreeGenerator.cs b/src/Microsoft.AspNet.Mvc.Razor/Compilation/SyntaxTreeGenerator.cs
index 0598a1a90e..0453ba051d 100644
--- a/src/Microsoft.AspNet.Mvc.Razor/Compilation/SyntaxTreeGenerator.cs
+++ b/src/Microsoft.AspNet.Mvc.Razor/Compilation/SyntaxTreeGenerator.cs
@@ -5,48 +5,29 @@ using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Text;
+using Microsoft.Framework.Runtime.Roslyn;
namespace Microsoft.AspNet.Mvc.Razor
{
public static class SyntaxTreeGenerator
{
- private static CSharpParseOptions DefaultOptions
- {
- get
- {
- return CSharpParseOptions.Default
- .WithLanguageVersion(LanguageVersion.CSharp6);
- }
- }
-
- public static SyntaxTree Generate([NotNull] string text, [NotNull] string path)
- {
- return GenerateCore(text, path, DefaultOptions);
- }
-
public static SyntaxTree Generate([NotNull] string text,
[NotNull] string path,
- [NotNull] CSharpParseOptions options)
- {
- return GenerateCore(text, path, options);
- }
-
- public static SyntaxTree GenerateCore([NotNull] string text,
- [NotNull] string path,
- [NotNull] CSharpParseOptions options)
+ [NotNull] CompilationSettings compilationSettings)
{
var sourceText = SourceText.From(text, Encoding.UTF8);
var syntaxTree = CSharpSyntaxTree.ParseText(sourceText,
path: path,
- options: options);
+ options: GetParseOptions(compilationSettings));
return syntaxTree;
}
- public static CSharpParseOptions GetParseOptions(CSharpCompilation compilation)
+ public static CSharpParseOptions GetParseOptions(CompilationSettings compilationSettings)
{
- return CSharpParseOptions.Default
- .WithLanguageVersion(compilation.LanguageVersion);
+ return new CSharpParseOptions(
+ languageVersion: compilationSettings.LanguageVersion,
+ preprocessorSymbols: compilationSettings.Defines.AsImmutable());
}
}
}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Razor/Razor/PreCompileViews/RazorFileInfoCollectionGenerator.cs b/src/Microsoft.AspNet.Mvc.Razor/Razor/PreCompileViews/RazorFileInfoCollectionGenerator.cs
index e7da94f301..956aa62d63 100644
--- a/src/Microsoft.AspNet.Mvc.Razor/Razor/PreCompileViews/RazorFileInfoCollectionGenerator.cs
+++ b/src/Microsoft.AspNet.Mvc.Razor/Razor/PreCompileViews/RazorFileInfoCollectionGenerator.cs
@@ -4,7 +4,7 @@
using System.Collections.Generic;
using System.Text;
using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.Framework.Runtime.Roslyn;
namespace Microsoft.AspNet.Mvc.Razor
{
@@ -13,13 +13,13 @@ namespace Microsoft.AspNet.Mvc.Razor
private string _fileFormat;
protected IReadOnlyList FileInfos { get; private set; }
- protected CSharpParseOptions Options { get; private set; }
+ protected CompilationSettings CompilationSettings { get; }
public RazorFileInfoCollectionGenerator([NotNull] IReadOnlyList fileInfos,
- [NotNull] CSharpParseOptions options)
+ [NotNull] CompilationSettings compilationSettings)
{
FileInfos = fileInfos;
- Options = options;
+ CompilationSettings = compilationSettings;
}
public virtual SyntaxTree GenerateCollection()
@@ -38,7 +38,7 @@ namespace Microsoft.AspNet.Mvc.Razor
var sourceCode = builder.ToString();
var syntaxTree = SyntaxTreeGenerator.Generate(sourceCode,
"__AUTO__GeneratedViewsCollection.cs",
- Options);
+ CompilationSettings);
return syntaxTree;
}
diff --git a/src/Microsoft.AspNet.Mvc.Razor/Razor/PreCompileViews/RazorPreCompiler.cs b/src/Microsoft.AspNet.Mvc.Razor/Razor/PreCompileViews/RazorPreCompiler.cs
index 2d69ef1ff6..b41c3bf017 100644
--- a/src/Microsoft.AspNet.Mvc.Razor/Razor/PreCompileViews/RazorPreCompiler.cs
+++ b/src/Microsoft.AspNet.Mvc.Razor/Razor/PreCompileViews/RazorPreCompiler.cs
@@ -10,6 +10,7 @@ using Microsoft.CodeAnalysis.CSharp;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel;
using Microsoft.Framework.Runtime;
+using Microsoft.Framework.Runtime.Roslyn;
namespace Microsoft.AspNet.Mvc.Razor
{
@@ -19,24 +20,28 @@ namespace Microsoft.AspNet.Mvc.Razor
private readonly IFileSystem _fileSystem;
private readonly IMvcRazorHost _host;
- public RazorPreCompiler([NotNull] IServiceProvider designTimeServiceProvider) :
+ public RazorPreCompiler([NotNull] IServiceProvider designTimeServiceProvider,
+ [NotNull] CompilationSettings compilationSettings) :
this(designTimeServiceProvider,
designTimeServiceProvider.GetRequiredService(),
- designTimeServiceProvider.GetRequiredService>())
+ designTimeServiceProvider.GetRequiredService>(),
+ compilationSettings)
{
}
public RazorPreCompiler([NotNull] IServiceProvider designTimeServiceProvider,
[NotNull] IMvcRazorHost host,
- [NotNull] IOptions optionsAccessor)
+ [NotNull] IOptions optionsAccessor,
+ [NotNull] CompilationSettings compilationSettings)
{
_serviceProvider = designTimeServiceProvider;
_host = host;
-
- var appEnv = _serviceProvider.GetRequiredService();
_fileSystem = optionsAccessor.Options.FileSystem;
+ CompilationSettings = compilationSettings;
}
+ protected CompilationSettings CompilationSettings { get; }
+
protected virtual string FileExtension { get; } = ".cshtml";
public virtual void CompileViews([NotNull] IBeforeCompileContext context)
@@ -47,7 +52,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{
var collectionGenerator = new RazorFileInfoCollectionGenerator(
descriptors,
- SyntaxTreeGenerator.GetParseOptions(context.CSharpCompilation));
+ CompilationSettings);
var tree = collectionGenerator.GenerateCollection();
context.CSharpCompilation = context.CSharpCompilation.AddSyntaxTrees(tree);
@@ -57,14 +62,11 @@ namespace Microsoft.AspNet.Mvc.Razor
protected virtual IReadOnlyList CreateCompilationDescriptors(
[NotNull] IBeforeCompileContext context)
{
- var options = SyntaxTreeGenerator.GetParseOptions(context.CSharpCompilation);
var list = new List();
foreach (var info in GetFileInfosRecursive(string.Empty))
{
- var descriptor = ParseView(info,
- context,
- options);
+ var descriptor = ParseView(info, context);
if (descriptor != null)
{
@@ -107,8 +109,7 @@ namespace Microsoft.AspNet.Mvc.Razor
}
protected virtual RazorFileInfo ParseView([NotNull] RelativeFileInfo fileInfo,
- [NotNull] IBeforeCompileContext context,
- [NotNull] CSharpParseOptions options)
+ [NotNull] IBeforeCompileContext context)
{
using (var stream = fileInfo.FileInfo.CreateReadStream())
{
@@ -124,7 +125,9 @@ namespace Microsoft.AspNet.Mvc.Razor
if (generatedCode != null)
{
- var syntaxTree = SyntaxTreeGenerator.Generate(generatedCode, fileInfo.FileInfo.PhysicalPath, options);
+ var syntaxTree = SyntaxTreeGenerator.Generate(generatedCode,
+ fileInfo.FileInfo.PhysicalPath,
+ CompilationSettings);
var fullTypeName = results.GetMainClassName(_host, syntaxTree);
if (fullTypeName != null)
diff --git a/src/Microsoft.AspNet.Mvc.Razor/project.json b/src/Microsoft.AspNet.Mvc.Razor/project.json
index f6db9c2334..239715bbc6 100644
--- a/src/Microsoft.AspNet.Mvc.Razor/project.json
+++ b/src/Microsoft.AspNet.Mvc.Razor/project.json
@@ -8,7 +8,7 @@
"Microsoft.AspNet.Mvc.Common": { "version": "6.0.0-*", "type": "build" },
"Microsoft.AspNet.Mvc.Core": "6.0.0-*",
"Microsoft.AspNet.Mvc.Razor.Host": "6.0.0-*",
- "Microsoft.CodeAnalysis.CSharp": "1.0.0-beta2-*"
+ "Microsoft.Framework.Runtime.Roslyn.Common": "1.0.0-*"
},
"frameworks": {
"aspnet50": {
diff --git a/src/Microsoft.AspNet.Mvc/MvcServices.cs b/src/Microsoft.AspNet.Mvc/MvcServices.cs
index d02390f793..6c7b832146 100644
--- a/src/Microsoft.AspNet.Mvc/MvcServices.cs
+++ b/src/Microsoft.AspNet.Mvc/MvcServices.cs
@@ -9,7 +9,6 @@ using Microsoft.AspNet.Mvc.Internal;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.OptionDescriptors;
using Microsoft.AspNet.Mvc.Razor;
-using Microsoft.AspNet.Mvc.Razor.Compilation;
using Microsoft.AspNet.Mvc.Razor.OptionDescriptors;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Mvc.Routing;
diff --git a/src/Microsoft.AspNet.Mvc/RazorPreCompileModule.cs b/src/Microsoft.AspNet.Mvc/RazorPreCompileModule.cs
index fa676ee056..e4f5298c1a 100644
--- a/src/Microsoft.AspNet.Mvc/RazorPreCompileModule.cs
+++ b/src/Microsoft.AspNet.Mvc/RazorPreCompileModule.cs
@@ -29,14 +29,17 @@ namespace Microsoft.AspNet.Mvc
public virtual void BeforeCompile(IBeforeCompileContext context)
{
- var appEnv = _appServices.GetRequiredService();
+ var applicationEnvironment = _appServices.GetRequiredService();
+ var compilerOptionsProvider = _appServices.GetRequiredService();
+ var compilationSettings = compilerOptionsProvider.GetCompilationSettings(applicationEnvironment);
- var setup = new RazorViewEngineOptionsSetup(appEnv);
+ var setup = new RazorViewEngineOptionsSetup(applicationEnvironment);
var sc = new ServiceCollection();
sc.ConfigureOptions(setup);
sc.AddMvc();
- var viewCompiler = new RazorPreCompiler(BuildFallbackServiceProvider(sc, _appServices));
+ var serviceProvider = BuildFallbackServiceProvider(sc, _appServices);
+ var viewCompiler = new RazorPreCompiler(serviceProvider, compilationSettings);
viewCompiler.CompileViews(context);
}
diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/CompilationOptionsTests.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/CompilationOptionsTests.cs
new file mode 100644
index 0000000000..ed5f3f1a32
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/CompilationOptionsTests.cs
@@ -0,0 +1,46 @@
+// Copyright (c) Microsoft Open Technologies, Inc. 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.Threading.Tasks;
+using Microsoft.AspNet.Builder;
+using Microsoft.AspNet.TestHost;
+using RazorWebSite;
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.FunctionalTests
+{
+ // Test to verify compilation options from the application are used to compile
+ // precompiled and dynamically compiled views.
+ public class CompilationOptionsTests
+ {
+ private readonly IServiceProvider _provider = TestHelper.CreateServices(nameof(RazorWebSite));
+ private readonly Action _app = new Startup().Configure;
+
+ [Fact]
+ public async Task CompilationOptions_AreUsedByViewsAndPartials()
+ {
+ // Arrange
+#if ASPNET50
+ var expected =
+@"This method is running from ASPNET50
+
+This method is only defined in ASPNET50";
+#elif ASPNETCORE50
+ var expected =
+@"This method is running from ASPNETCORE50
+
+This method is only defined in ASPNETCORE50";
+#endif
+ var server = TestServer.Create(_provider, _app);
+ var client = server.CreateClient();
+
+ // Act
+ var body = await client.GetStringAsync("http://localhost/ViewsConsumingCompilationOptions/");
+
+ // Assert
+ Assert.Equal(expected, body.Trim());
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/PrecompilationTest.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/PrecompilationTest.cs
index 2e4945701a..307fb7751e 100644
--- a/test/Microsoft.AspNet.Mvc.FunctionalTests/PrecompilationTest.cs
+++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/PrecompilationTest.cs
@@ -11,6 +11,7 @@ using Microsoft.AspNet.Builder;
using Microsoft.AspNet.TestHost;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.Runtime;
+using PrecompilationWebSite;
using Xunit;
namespace Microsoft.AspNet.Mvc.FunctionalTests
@@ -18,8 +19,8 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
public class PrecompilationTest
{
private static readonly TimeSpan _cacheDelayInterval = TimeSpan.FromSeconds(2);
- private readonly IServiceProvider _services = TestHelper.CreateServices("PrecompilationWebSite");
- private readonly Action _app = new PrecompilationWebSite.Startup().Configure;
+ private readonly IServiceProvider _services = TestHelper.CreateServices(nameof(PrecompilationWebSite));
+ private readonly Action _app = new Startup().Configure;
[Fact]
public async Task PrecompiledView_RendersCorrectly()
@@ -37,7 +38,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
// We will render a view that writes the fully qualified name of the Assembly containing the type of
// the view. If the view is precompiled, this assembly will be PrecompilationWebsite.
- var assemblyName = typeof(PrecompilationWebSite.Startup).GetTypeInfo().Assembly.GetName().ToString();
+ var assemblyName = typeof(Startup).GetTypeInfo().Assembly.GetName().ToString();
try
{
@@ -142,6 +143,30 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
}
}
+ [Fact]
+ public async Task PrecompiledView_UsesCompilationOptionsFromApplication()
+ {
+ // Arrange
+ var assemblyName = typeof(Startup).GetTypeInfo().Assembly.GetName().ToString();
+#if ASPNET50
+ var expected =
+@"Value set inside ASPNET50 " + assemblyName;
+#elif ASPNETCORE50
+ var expected =
+@"Value set inside ASPNETCORE50 " + assemblyName;
+#endif
+
+ var server = TestServer.Create(_services, _app);
+ var client = server.CreateClient();
+
+ // Act
+ var response = await client.GetAsync("http://localhost/Home/PrecompiledViewsCanConsumeCompilationOptions");
+ var responseContent = await response.Content.ReadAsStringAsync();
+
+ // Assert
+ Assert.Equal(expected, responseContent.Trim());
+ }
+
private static Task TouchFile(string viewsDir, string file)
{
File.AppendAllText(Path.Combine(viewsDir, file), " ");
diff --git a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorCompilationServiceTest.cs b/test/Microsoft.AspNet.Mvc.Razor.Test/Compilation/RazorCompilationServiceTest.cs
similarity index 100%
rename from test/Microsoft.AspNet.Mvc.Razor.Test/RazorCompilationServiceTest.cs
rename to test/Microsoft.AspNet.Mvc.Razor.Test/Compilation/RazorCompilationServiceTest.cs
diff --git a/test/Microsoft.AspNet.Mvc.Razor.Test/Compilation/RoslynCompilationServiceTest.cs b/test/Microsoft.AspNet.Mvc.Razor.Test/Compilation/RoslynCompilationServiceTest.cs
new file mode 100644
index 0000000000..ebc6bfb26f
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.Razor.Test/Compilation/RoslynCompilationServiceTest.cs
@@ -0,0 +1,170 @@
+// Copyright (c) Microsoft Open Technologies, Inc. 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.IO;
+using System.Reflection;
+using System.Runtime.Versioning;
+using Microsoft.Framework.Runtime;
+using Moq;
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.Razor
+{
+ public class RoslynCompilationServiceTest
+ {
+ [Fact]
+ public void Compile_ReturnsUncachedCompilationResultWithCompiledContent()
+ {
+ // Arrange
+ var content = @"
+public class MyTestType {}";
+ var applicationEnvironment = GetApplicationEnvironment();
+ var accessor = GetLoadContextAccessor();
+ var libraryManager = GetLibraryManager();
+
+ var compilerOptionsProvider = new Mock();
+ compilerOptionsProvider.Setup(p => p.GetCompilerOptions(applicationEnvironment.ApplicationBasePath,
+ applicationEnvironment.RuntimeFramework,
+ applicationEnvironment.Configuration))
+ .Returns(new CompilerOptions());
+ var mvcRazorHost = new Mock();
+ mvcRazorHost.SetupGet(m => m.MainClassNamePrefix)
+ .Returns(string.Empty);
+
+ var compilationService = new RoslynCompilationService(applicationEnvironment,
+ accessor,
+ libraryManager,
+ compilerOptionsProvider.Object,
+ mvcRazorHost.Object);
+
+ // Act
+ var result = compilationService.Compile(new TestFileInfo { PhysicalPath = "SomePath" }, content);
+
+ // Assert
+ var uncachedResult = Assert.IsType(result);
+ Assert.Equal("MyTestType", result.CompiledType.Name);
+ Assert.Equal(content, result.CompiledContent);
+ }
+
+ [Fact]
+ public void Compile_UsesApplicationsCompilationSettings_ForParsingAndCompilation()
+ {
+ // Arrange
+ var content = @"
+#if MY_CUSTOM_DEFINE
+public class MyCustomDefinedClass {}
+#else
+public class MyNonCustomDefinedClass {}
+#endif
+";
+ var applicationEnvironment = GetApplicationEnvironment();
+ var accessor = GetLoadContextAccessor();
+ var libraryManager = GetLibraryManager();
+
+ var compilerOptionsProvider = new Mock();
+ compilerOptionsProvider.Setup(p => p.GetCompilerOptions(applicationEnvironment.ApplicationBasePath,
+ applicationEnvironment.RuntimeFramework,
+ applicationEnvironment.Configuration))
+ .Returns(new CompilerOptions { Defines = new[] { "MY_CUSTOM_DEFINE" } });
+ var mvcRazorHost = new Mock();
+ mvcRazorHost.SetupGet(m => m.MainClassNamePrefix)
+ .Returns("My");
+
+ var compilationService = new RoslynCompilationService(applicationEnvironment,
+ accessor,
+ libraryManager,
+ compilerOptionsProvider.Object,
+ mvcRazorHost.Object);
+
+ // Act
+ var result = compilationService.Compile(new TestFileInfo { PhysicalPath = "SomePath" }, content);
+
+ // Assert
+ Assert.NotNull(result.CompiledType);
+ Assert.Equal("MyCustomDefinedClass", result.CompiledType.Name);
+ }
+
+ [Fact]
+ public void Compile_ReturnsSingleTypeThatStartsWithMainClassNamePrefix()
+ {
+ // Arrange
+ var content = @"
+public class RazorPrefixType {}
+public class NotRazorPrefixType {}";
+ var applicationEnvironment = GetApplicationEnvironment();
+ var accessor = GetLoadContextAccessor();
+ var libraryManager = GetLibraryManager();
+
+ var compilerOptionsProvider = new Mock();
+ compilerOptionsProvider.Setup(p => p.GetCompilerOptions(applicationEnvironment.ApplicationBasePath,
+ applicationEnvironment.RuntimeFramework,
+ applicationEnvironment.Configuration))
+ .Returns(new CompilerOptions());
+ var mvcRazorHost = new Mock();
+ mvcRazorHost.SetupGet(m => m.MainClassNamePrefix)
+ .Returns("RazorPrefix");
+
+ var compilationService = new RoslynCompilationService(applicationEnvironment,
+ accessor,
+ libraryManager,
+ compilerOptionsProvider.Object,
+ mvcRazorHost.Object);
+
+ // Act
+ var result = compilationService.Compile(new TestFileInfo { PhysicalPath = "SomePath" }, content);
+
+ // Assert
+ Assert.NotNull(result.CompiledType);
+ Assert.Equal("RazorPrefixType", result.CompiledType.Name);
+ }
+
+ private static ILibraryManager GetLibraryManager()
+ {
+ var fileReference = new Mock();
+ fileReference.SetupGet(f => f.Path)
+ .Returns(typeof(string).Assembly.Location);
+ var libraryExport = new Mock();
+ libraryExport.SetupGet(e => e.MetadataReferences)
+ .Returns(new[] { fileReference.Object });
+ libraryExport.SetupGet(e => e.SourceReferences)
+ .Returns(new ISourceReference[0]);
+
+ var libraryManager = new Mock();
+ libraryManager.Setup(l => l.GetAllExports(It.IsAny()))
+ .Returns(libraryExport.Object);
+ return libraryManager.Object;
+ }
+
+ private static IAssemblyLoadContextAccessor GetLoadContextAccessor()
+ {
+ var loadContext = new Mock();
+ loadContext.Setup(s => s.LoadStream(It.IsAny(), It.IsAny()))
+ .Returns((Stream stream, Stream pdb) =>
+ {
+ var memoryStream = (MemoryStream)stream;
+ return Assembly.Load(memoryStream.ToArray());
+ });
+
+ var accessor = new Mock();
+ accessor.Setup(a => a.GetLoadContext(typeof(RoslynCompilationService).Assembly))
+ .Returns(loadContext.Object);
+ return accessor.Object;
+ }
+
+ private IApplicationEnvironment GetApplicationEnvironment()
+ {
+ var applicationEnvironment = new Mock();
+ applicationEnvironment.SetupGet(a => a.ApplicationName)
+ .Returns("MyApp");
+ applicationEnvironment.SetupGet(a => a.RuntimeFramework)
+ .Returns(new FrameworkName("ASPNET", new Version(5, 0)));
+ applicationEnvironment.SetupGet(a => a.Configuration)
+ .Returns("Debug");
+ applicationEnvironment.SetupGet(a => a.ApplicationBasePath)
+ .Returns("MyBasePath");
+
+ return applicationEnvironment.Object;
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/WebSites/PrecompilationWebSite/Controllers/HomeController.cs b/test/WebSites/PrecompilationWebSite/Controllers/HomeController.cs
index bdff9e4876..7fca420d2e 100644
--- a/test/WebSites/PrecompilationWebSite/Controllers/HomeController.cs
+++ b/test/WebSites/PrecompilationWebSite/Controllers/HomeController.cs
@@ -11,5 +11,10 @@ namespace PrecompilationWebSite.Controllers
{
return View();
}
+
+ public IActionResult PrecompiledViewsCanConsumeCompilationOptions()
+ {
+ return View("~/Views/ViewsConsumingCompilationOptions/Index");
+ }
}
}
diff --git a/test/WebSites/PrecompilationWebSite/Views/ViewsConsumingCompilationOptions/Index.cshtml b/test/WebSites/PrecompilationWebSite/Views/ViewsConsumingCompilationOptions/Index.cshtml
new file mode 100644
index 0000000000..58b2a8d961
--- /dev/null
+++ b/test/WebSites/PrecompilationWebSite/Views/ViewsConsumingCompilationOptions/Index.cshtml
@@ -0,0 +1,9 @@
+@{
+string message =
+#if ASPNET50
+ "Value set inside ASPNET50 " + GetType().Assembly.FullName;
+#elif ASPNETCORE50
+ "Value set inside ASPNETCORE50 " + System.Reflection.IntrospectionExtensions.GetTypeInfo(GetType()).Assembly.FullName;
+#endif
+}
+@message
diff --git a/test/WebSites/PrecompilationWebSite/project.json b/test/WebSites/PrecompilationWebSite/project.json
index 01696e38f0..3f6e124d78 100644
--- a/test/WebSites/PrecompilationWebSite/project.json
+++ b/test/WebSites/PrecompilationWebSite/project.json
@@ -12,8 +12,16 @@
"Microsoft.AspNet.StaticFiles": "1.0.0-*"
},
"frameworks": {
- "aspnet50": { },
- "aspnetcore50": { }
+ "aspnet50": {
+ "compilationOptions": {
+ "define": [ "CUSTOM_ASPNET50_DEFINE" ]
+ }
+ },
+ "aspnetcore50": {
+ "compilationOptions": {
+ "define": [ "CUSTOM_ASPNETCORE50_DEFINE" ]
+ }
+ }
},
"webroot": "wwwroot"
}
diff --git a/test/WebSites/RazorWebSite/Controllers/ViewsConsumingCompilationOptionsController.cs b/test/WebSites/RazorWebSite/Controllers/ViewsConsumingCompilationOptionsController.cs
new file mode 100644
index 0000000000..9144cae9a9
--- /dev/null
+++ b/test/WebSites/RazorWebSite/Controllers/ViewsConsumingCompilationOptionsController.cs
@@ -0,0 +1,17 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using Microsoft.AspNet.Mvc;
+
+namespace RazorWebSite.Controllers
+{
+ // Views returned by this controller use #ifdefs for defines specified in project.json
+ // The intent of this controller is to verify that view compilation uses the app's compilation settings.
+ public class ViewsConsumingCompilationOptionsController : Controller
+ {
+ public ViewResult Index()
+ {
+ return View();
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/WebSites/RazorWebSite/Services/FrameworkSpecificHelper.cs b/test/WebSites/RazorWebSite/Services/FrameworkSpecificHelper.cs
new file mode 100644
index 0000000000..5c8cbf01f8
--- /dev/null
+++ b/test/WebSites/RazorWebSite/Services/FrameworkSpecificHelper.cs
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+namespace RazorWebSite
+{
+ public class FrameworkSpecificHelper
+ {
+ public string ExecuteOperation()
+ {
+#if ASPNET50
+ return "This method is running from ASPNET50";
+#elif ASPNETCORE50
+ return "This method is running from ASPNETCORE50";
+#endif
+ }
+
+#if ASPNET50_CUSTOM_DEFINE
+ public string ExecuteAspNet50Operation()
+ {
+ return "This method is only defined in ASPNET50";
+ }
+#endif
+
+#if ASPNETCORE50_CUSTOM_DEFINE
+ public string ExecuteAspNetCore50Operation()
+ {
+ return "This method is only defined in ASPNETCORE50";
+ }
+#endif
+ }
+}
\ No newline at end of file
diff --git a/test/WebSites/RazorWebSite/Startup.cs b/test/WebSites/RazorWebSite/Startup.cs
index ae70ef8d0f..91a7547720 100644
--- a/test/WebSites/RazorWebSite/Startup.cs
+++ b/test/WebSites/RazorWebSite/Startup.cs
@@ -21,6 +21,7 @@ namespace RazorWebSite
services.AddMvc(configuration);
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
services.Configure(options =>
{
var expander = new LanguageViewLocationExpander(
diff --git a/test/WebSites/RazorWebSite/Views/ViewsConsumingCompilationOptions/Index.cshtml b/test/WebSites/RazorWebSite/Views/ViewsConsumingCompilationOptions/Index.cshtml
new file mode 100644
index 0000000000..71684f7ea6
--- /dev/null
+++ b/test/WebSites/RazorWebSite/Views/ViewsConsumingCompilationOptions/Index.cshtml
@@ -0,0 +1,3 @@
+@inject FrameworkSpecificHelper MyHelper
+@MyHelper.ExecuteOperation()
+@Html.Partial("_Partial")
\ No newline at end of file
diff --git a/test/WebSites/RazorWebSite/Views/ViewsConsumingCompilationOptions/_Partial.cshtml b/test/WebSites/RazorWebSite/Views/ViewsConsumingCompilationOptions/_Partial.cshtml
new file mode 100644
index 0000000000..9234f21545
--- /dev/null
+++ b/test/WebSites/RazorWebSite/Views/ViewsConsumingCompilationOptions/_Partial.cshtml
@@ -0,0 +1,11 @@
+@inject FrameworkSpecificHelper MyHelper
+@{
+ string value =
+#if ASPNET50_CUSTOM_DEFINE
+ MyHelper.ExecuteAspNet50Operation();
+#endif
+#if ASPNETCORE50_CUSTOM_DEFINE
+ MyHelper.ExecuteAspNetCore50Operation();
+#endif
+}
+@value
\ No newline at end of file
diff --git a/test/WebSites/RazorWebSite/project.json b/test/WebSites/RazorWebSite/project.json
index c582a1382f..25816ad6c7 100644
--- a/test/WebSites/RazorWebSite/project.json
+++ b/test/WebSites/RazorWebSite/project.json
@@ -12,8 +12,16 @@
"Microsoft.AspNet.StaticFiles": "1.0.0-*"
},
"frameworks": {
- "aspnet50": { },
- "aspnetcore50": { }
+ "aspnet50": {
+ "compilationOptions": {
+ "define": [ "ASPNET50_CUSTOM_DEFINE" ]
+ }
+ },
+ "aspnetcore50": {
+ "compilationOptions": {
+ "define": [ "ASPNETCORE50_CUSTOM_DEFINE" ]
+ }
+ }
},
"webroot": "wwwroot"
}