diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/DefaultRoslynCompilationService.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/DefaultRoslynCompilationService.cs
index 8fbb8945f4..833c541949 100644
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/DefaultRoslynCompilationService.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/DefaultRoslynCompilationService.cs
@@ -27,6 +27,12 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
///
public class DefaultRoslynCompilationService : ICompilationService
{
+ // error CS0234: The type or namespace name 'C' does not exist in the namespace 'N' (are you missing
+ // an assembly reference?)
+ private const string CS0234 = nameof(CS0234);
+ // error CS0246: The type or namespace name 'T' could not be found (are you missing a using directive
+ // or an assembly reference?)
+ private const string CS0246 = nameof(CS0246);
private readonly DebugInformationFormat _pdbFormat =
#if NET451
SymbolsUtility.SupportsFullPdbGeneration() ?
@@ -128,18 +134,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
if (!result.Success)
{
- if (!compilation.References.Any() && !CompilationReferences.Any())
- {
- // DependencyModel had no references specified and the user did not use the
- // CompilationCallback to add extra references. It is likely that the user did not specify
- // preserveCompilationContext in the app's project.json.
- throw new InvalidOperationException(
- Resources.FormatCompilation_DependencyContextIsNotSpecified(
- fileInfo.RelativePath,
- "project.json",
- "preserveCompilationContext"));
- }
-
return GetCompilationFailedResult(
fileInfo.RelativePath,
compilationContent,
@@ -232,11 +226,23 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
sourceFileContent = ReadFileContentsSafely(_fileProvider, sourceFilePath);
}
+ string additionalMessage = null;
+ if (group.Any(g =>
+ string.Equals(CS0234, g.Id, StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(CS0246, g.Id, StringComparison.OrdinalIgnoreCase)))
+ {
+ additionalMessage = Resources.FormatCompilation_DependencyContextIsNotSpecified(
+ "preserveCompilationContext",
+ "buildOptions",
+ "project.json");
+ }
+
var compilationFailure = new CompilationFailure(
sourceFilePath,
sourceFileContent,
compilationContent,
- group.Select(GetDiagnosticMessage));
+ group.Select(GetDiagnosticMessage),
+ additionalMessage);
failures.Add(compilationFailure);
}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Properties/Resources.Designer.cs
index 9552b4a630..f53ef11e26 100644
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Properties/Resources.Designer.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/Properties/Resources.Designer.cs
@@ -447,7 +447,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor
}
///
- /// The Razor page '{0}' failed to compile. Ensure that your application's {1} sets the '{2}' compilation property.
+ /// One or more compilation references are missing. Possible causes include a missing '{0}' property under '{1}' in the application's {2}.
///
internal static string Compilation_DependencyContextIsNotSpecified
{
@@ -455,7 +455,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor
}
///
- /// The Razor page '{0}' failed to compile. Ensure that your application's {1} sets the '{2}' compilation property.
+ /// One or more compilation references are missing. Possible causes include a missing '{0}' property under '{1}' in the application's {2}.
///
internal static string FormatCompilation_DependencyContextIsNotSpecified(object p0, object p1, object p2)
{
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Resources.resx b/src/Microsoft.AspNetCore.Mvc.Razor/Resources.resx
index 6e402095f5..c0d7484574 100644
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Resources.resx
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/Resources.resx
@@ -201,7 +201,7 @@
A circular layout reference was detected when rendering '{0}'. The layout page '{1}' has already been rendered.
- The Razor page '{0}' failed to compile. Ensure that your application's {1} sets the '{2}' compilation property.
+ One or more compilation references are missing. Possible causes include a missing '{0}' property under '{1}' in the application's {2}.
'{0}' cannot be empty. These locations are required to locate a view for rendering.
diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ErrorPageTests.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ErrorPageTests.cs
index 818e2082bb..bc077e798e 100644
--- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ErrorPageTests.cs
+++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ErrorPageTests.cs
@@ -16,6 +16,9 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
///
public class ErrorPageTests : IClassFixture>
{
+ private static readonly string PreserveCompilationContextMessage = HtmlEncoder.Default.Encode(
+ "One or more compilation references are missing. Possible causes include a missing " +
+ "'preserveCompilationContext' property under 'buildOptions' in the application's project.json.");
public ErrorPageTests(MvcTestFixture fixture)
{
Client = fixture.Client;
@@ -23,21 +26,40 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
public HttpClient Client { get; }
- [Theory]
- [InlineData("CompilationFailure", "Cannot implicitly convert type 'int' to 'string'")]
- [InlineData("ParserError",
- "The code block is missing a closing "}" character. Make sure you " +
- "have a matching "}" character for all the "{" characters " +
- "within this block, and that none of the "}" characters are being " +
- "interpreted as markup.")]
- public async Task CompilationFailuresAreListedByErrorPageMiddleware(string action, string expected)
+ [Fact]
+ public async Task CompilationFailuresAreListedByErrorPageMiddleware()
{
// Arrange
+ var action = "CompilationFailure";
+ var expected = "Cannot implicitly convert type 'int' to 'string'";
var expectedMediaType = MediaTypeHeaderValue.Parse("text/html; charset=utf-8");
// Act
var response = await Client.GetAsync("http://localhost/" + action);
+ // Assert
+ Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
+ Assert.Equal(expectedMediaType, response.Content.Headers.ContentType);
+ var content = await response.Content.ReadAsStringAsync();
+ Assert.Contains($"/Views/ErrorPageMiddleware/{action}.cshtml", content);
+ Assert.Contains(expected, content);
+ Assert.DoesNotContain(PreserveCompilationContextMessage, content);
+ }
+
+ [Fact]
+ public async Task ParseFailuresAreListedByErrorPageMiddleware()
+ {
+ // Arrange
+ var action = "ParserError";
+ var expected = "The code block is missing a closing "}" character. Make sure you " +
+ "have a matching "}" character for all the "{" characters " +
+ "within this block, and that none of the "}" characters are being " +
+ "interpreted as markup.";
+ var expectedMediaType = MediaTypeHeaderValue.Parse("text/html; charset=utf-8");
+
+ // Act
+ var response = await Client.GetAsync(action);
+
// Assert
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
Assert.Equal(expectedMediaType, response.Content.Headers.ContentType);
@@ -63,6 +85,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
var content = await response.Content.ReadAsStringAsync();
Assert.Contains("/Views/ErrorFromViewImports/_ViewImports.cshtml", content);
Assert.Contains(expectedMessage, content);
+ Assert.Contains(PreserveCompilationContextMessage, content);
}
[Fact]
diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DefaultRoslynCompilationServiceTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DefaultRoslynCompilationServiceTest.cs
index 957ddced77..6a320d51ad 100644
--- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DefaultRoslynCompilationServiceTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DefaultRoslynCompilationServiceTest.cs
@@ -248,27 +248,6 @@ public class MyNonCustomDefinedClass {}
Assert.Single(usedCompilation.Compilation.SyntaxTrees);
}
- [Fact]
- public void Compile_ThrowsIfNoMetadataReferencesAreDiscoveredAndApplicationFailsToCompile()
- {
- // Arrange
- var content = "public class MyTestType {}";
- var applicationPartManager = new ApplicationPartManager();
- var compilationService = GetRoslynCompilationService(applicationPartManager);
-
- 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_DoesNotThrowIfReferencesWereClearedInCallback()
{