diff --git a/build/dependencies.props b/build/dependencies.props
index 90660e53c..6f2f0187d 100644
--- a/build/dependencies.props
+++ b/build/dependencies.props
@@ -40,9 +40,7 @@
3.0.0-alpha1-10742
3.0.0-alpha1-10742
3.0.0-alpha1-10742
- 3.0.0-alpha1-10742
3.0.0-alpha1-10742
- 3.0.0-alpha1-10742
3.0.0-alpha1-10742
3.0.0-alpha1-10742
3.0.0-alpha1-10742
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ApplicationParts/ApplicationAssembliesProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/ApplicationParts/ApplicationAssembliesProvider.cs
index 9b222e72b..b1d414a8c 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ApplicationParts/ApplicationAssembliesProvider.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ApplicationParts/ApplicationAssembliesProvider.cs
@@ -28,7 +28,6 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationParts
"Microsoft.AspNetCore.Mvc.Formatters.Xml",
"Microsoft.AspNetCore.Mvc.Localization",
"Microsoft.AspNetCore.Mvc.Razor",
- "Microsoft.AspNetCore.Mvc.Razor.Extensions",
"Microsoft.AspNetCore.Mvc.RazorPages",
"Microsoft.AspNetCore.Mvc.TagHelpers",
"Microsoft.AspNetCore.Mvc.ViewFeatures",
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/CSharpCompiler.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/CSharpCompiler.cs
deleted file mode 100644
index c4f58943f..000000000
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/CSharpCompiler.cs
+++ /dev/null
@@ -1,234 +0,0 @@
-// 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.Diagnostics;
-using System.Linq;
-using System.Reflection;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.Emit;
-using Microsoft.CodeAnalysis.Text;
-using Microsoft.Extensions.DependencyModel;
-using DependencyContextCompilationOptions = Microsoft.Extensions.DependencyModel.CompilationOptions;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
-{
- internal class CSharpCompiler
- {
-#pragma warning disable CS0618 // Type or member is obsolete
- private readonly RazorReferenceManager _referenceManager;
-#pragma warning restore CS0618 // Type or member is obsolete
- private readonly IHostingEnvironment _hostingEnvironment;
- private bool _optionsInitialized;
- private CSharpParseOptions _parseOptions;
- private CSharpCompilationOptions _compilationOptions;
- private EmitOptions _emitOptions;
- private bool _emitPdb;
-
-#pragma warning disable CS0618 // Type or member is obsolete
- public CSharpCompiler(RazorReferenceManager manager, IHostingEnvironment hostingEnvironment)
-#pragma warning restore CS0618 // Type or member is obsolete
- {
- _referenceManager = manager ?? throw new ArgumentNullException(nameof(manager));
- _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
- }
-
- public virtual CSharpParseOptions ParseOptions
- {
- get
- {
- EnsureOptions();
- return _parseOptions;
- }
- }
-
- public virtual CSharpCompilationOptions CSharpCompilationOptions
- {
- get
- {
- EnsureOptions();
- return _compilationOptions;
- }
- }
-
- public virtual bool EmitPdb
- {
- get
- {
- EnsureOptions();
- return _emitPdb;
- }
- }
-
- public virtual EmitOptions EmitOptions
- {
- get
- {
- EnsureOptions();
- return _emitOptions;
- }
- }
-
- public SyntaxTree CreateSyntaxTree(SourceText sourceText)
- {
- return CSharpSyntaxTree.ParseText(
- sourceText,
- options: ParseOptions);
- }
-
- public CSharpCompilation CreateCompilation(string assemblyName)
- {
- return CSharpCompilation.Create(
- assemblyName,
- options: CSharpCompilationOptions,
- references: _referenceManager.CompilationReferences);
- }
-
- // Internal for unit testing.
- protected internal virtual DependencyContextCompilationOptions GetDependencyContextCompilationOptions()
- {
- if (!string.IsNullOrEmpty(_hostingEnvironment.ApplicationName))
- {
- var applicationAssembly = Assembly.Load(new AssemblyName(_hostingEnvironment.ApplicationName));
- var dependencyContext = DependencyContext.Load(applicationAssembly);
- if (dependencyContext?.CompilationOptions != null)
- {
- return dependencyContext.CompilationOptions;
- }
- }
-
- return DependencyContextCompilationOptions.Default;
- }
-
- private void EnsureOptions()
- {
- if (!_optionsInitialized)
- {
- var dependencyContextOptions = GetDependencyContextCompilationOptions();
- _parseOptions = GetParseOptions(_hostingEnvironment, dependencyContextOptions);
- _compilationOptions = GetCompilationOptions(_hostingEnvironment, dependencyContextOptions);
- _emitOptions = GetEmitOptions(dependencyContextOptions);
-
- _optionsInitialized = true;
- }
- }
-
- private EmitOptions GetEmitOptions(DependencyContextCompilationOptions dependencyContextOptions)
- {
- // Assume we're always producing pdbs unless DebugType = none
- _emitPdb = true;
- DebugInformationFormat debugInformationFormat;
- if (string.IsNullOrEmpty(dependencyContextOptions.DebugType))
- {
- debugInformationFormat = SymbolsUtility.SupportsFullPdbGeneration() ?
- DebugInformationFormat.Pdb :
- DebugInformationFormat.PortablePdb;
- }
- else
- {
- // Based on https://github.com/dotnet/roslyn/blob/1d28ff9ba248b332de3c84d23194a1d7bde07e4d/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs#L624-L640
- switch (dependencyContextOptions.DebugType.ToLower())
- {
- case "none":
- // There isn't a way to represent none in DebugInformationFormat.
- // We'll set EmitPdb to false and let callers handle it by setting a null pdb-stream.
- _emitPdb = false;
- return new EmitOptions();
- case "portable":
- debugInformationFormat = DebugInformationFormat.PortablePdb;
- break;
- case "embedded":
- // Roslyn does not expose enough public APIs to produce a binary with embedded pdbs.
- // We'll produce PortablePdb instead to continue providing a reasonable user experience.
- debugInformationFormat = DebugInformationFormat.PortablePdb;
- break;
- case "full":
- case "pdbonly":
- debugInformationFormat = SymbolsUtility.SupportsFullPdbGeneration() ?
- DebugInformationFormat.Pdb :
- DebugInformationFormat.PortablePdb;
- break;
- default:
- throw new InvalidOperationException(Resources.FormatUnsupportedDebugInformationFormat(dependencyContextOptions.DebugType));
- }
- }
-
- var emitOptions = new EmitOptions(debugInformationFormat: debugInformationFormat);
- return emitOptions;
- }
-
- private static CSharpCompilationOptions GetCompilationOptions(
- IHostingEnvironment hostingEnvironment,
- DependencyContextCompilationOptions dependencyContextOptions)
- {
- var csharpCompilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
-
- // Disable 1702 until roslyn turns this off by default
- csharpCompilationOptions = csharpCompilationOptions.WithSpecificDiagnosticOptions(
- new Dictionary
- {
- {"CS1701", ReportDiagnostic.Suppress}, // Binding redirects
- {"CS1702", ReportDiagnostic.Suppress},
- {"CS1705", ReportDiagnostic.Suppress}
- });
-
- if (dependencyContextOptions.AllowUnsafe.HasValue)
- {
- csharpCompilationOptions = csharpCompilationOptions.WithAllowUnsafe(
- dependencyContextOptions.AllowUnsafe.Value);
- }
-
- OptimizationLevel optimizationLevel;
- if (dependencyContextOptions.Optimize.HasValue)
- {
- optimizationLevel = dependencyContextOptions.Optimize.Value ?
- OptimizationLevel.Release :
- OptimizationLevel.Debug;
- }
- else
- {
- optimizationLevel = hostingEnvironment.IsDevelopment() ?
- OptimizationLevel.Debug :
- OptimizationLevel.Release;
- }
- csharpCompilationOptions = csharpCompilationOptions.WithOptimizationLevel(optimizationLevel);
-
- if (dependencyContextOptions.WarningsAsErrors.HasValue)
- {
- var reportDiagnostic = dependencyContextOptions.WarningsAsErrors.Value ?
- ReportDiagnostic.Error :
- ReportDiagnostic.Default;
- csharpCompilationOptions = csharpCompilationOptions.WithGeneralDiagnosticOption(reportDiagnostic);
- }
-
- return csharpCompilationOptions;
- }
-
- private static CSharpParseOptions GetParseOptions(
- IHostingEnvironment hostingEnvironment,
- DependencyContextCompilationOptions dependencyContextOptions)
- {
- var configurationSymbol = hostingEnvironment.IsDevelopment() ? "DEBUG" : "RELEASE";
- var defines = dependencyContextOptions.Defines.Concat(new[] { configurationSymbol });
-
- var parseOptions = new CSharpParseOptions(preprocessorSymbols: defines);
-
- if (!string.IsNullOrEmpty(dependencyContextOptions.LanguageVersion))
- {
- if (LanguageVersionFacts.TryParse(dependencyContextOptions.LanguageVersion, out var languageVersion))
- {
- parseOptions = parseOptions.WithLanguageVersion(languageVersion);
- }
- else
- {
- Debug.Fail($"LanguageVersion {languageVersion} specified in the deps file could not be parsed.");
- }
- }
-
- return parseOptions;
- }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/ChecksumValidator.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/ChecksumValidator.cs
deleted file mode 100644
index 2e5df4a3a..000000000
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/ChecksumValidator.cs
+++ /dev/null
@@ -1,122 +0,0 @@
-// 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.Linq;
-using Microsoft.AspNetCore.Razor.Hosting;
-using Microsoft.AspNetCore.Razor.Language;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
-{
- internal static class ChecksumValidator
- {
- public static bool IsRecompilationSupported(RazorCompiledItem item)
- {
- if (item == null)
- {
- throw new ArgumentNullException(nameof(item));
- }
-
- // A Razor item only supports recompilation if its primary source file has a checksum.
- //
- // Other files (view imports) may or may not have existed at the time of compilation,
- // so we may not have checksums for them.
- var checksums = item.GetChecksumMetadata();
- return checksums.Any(c => string.Equals(item.Identifier, c.Identifier, StringComparison.OrdinalIgnoreCase));
- }
-
- // Validates that we can use an existing precompiled view by comparing checksums with files on
- // disk.
- public static bool IsItemValid(RazorProjectFileSystem fileSystem, RazorCompiledItem item)
- {
- if (fileSystem == null)
- {
- throw new ArgumentNullException(nameof(fileSystem));
- }
-
- if (item == null)
- {
- throw new ArgumentNullException(nameof(item));
- }
-
- var checksums = item.GetChecksumMetadata();
-
- // The checksum that matches 'Item.Identity' in this list is significant. That represents the main file.
- //
- // We don't really care about the validation unless the main file exists. This is because we expect
- // most sites to have some _ViewImports in common location. That means that in the case you're
- // using views from a 3rd party library, you'll always have **some** conflicts.
- //
- // The presence of the main file with the same content is a very strong signal that you're in a
- // development scenario.
- var primaryChecksum = checksums
- .FirstOrDefault(c => string.Equals(item.Identifier, c.Identifier, StringComparison.OrdinalIgnoreCase));
- if (primaryChecksum == null)
- {
- // No primary checksum, assume valid.
- return true;
- }
-
- var projectItem = fileSystem.GetItem(primaryChecksum.Identifier);
- if (!projectItem.Exists)
- {
- // Main file doesn't exist - assume valid.
- return true;
- }
-
- var sourceDocument = RazorSourceDocument.ReadFrom(projectItem);
- if (!string.Equals(sourceDocument.GetChecksumAlgorithm(), primaryChecksum.ChecksumAlgorithm) ||
- !ChecksumsEqual(primaryChecksum.Checksum, sourceDocument.GetChecksum()))
- {
- // Main file exists, but checksums not equal.
- return false;
- }
-
- for (var i = 0; i < checksums.Count; i++)
- {
- var checksum = checksums[i];
- if (string.Equals(item.Identifier, checksum.Identifier, StringComparison.OrdinalIgnoreCase))
- {
- // Ignore primary checksum on this pass.
- continue;
- }
-
- var importItem = fileSystem.GetItem(checksum.Identifier);
- if (!importItem.Exists)
- {
- // Import file doesn't exist - assume invalid.
- return false;
- }
-
- sourceDocument = RazorSourceDocument.ReadFrom(importItem);
- if (!string.Equals(sourceDocument.GetChecksumAlgorithm(), checksum.ChecksumAlgorithm) ||
- !ChecksumsEqual(checksum.Checksum, sourceDocument.GetChecksum()))
- {
- // Import file exists, but checksums not equal.
- return false;
- }
- }
-
- return true;
- }
-
- private static bool ChecksumsEqual(string checksum, byte[] bytes)
- {
- if (bytes.Length * 2 != checksum.Length)
- {
- return false;
- }
-
- for (var i = 0; i < bytes.Length; i++)
- {
- var text = bytes[i].ToString("x2");
- if (checksum[i * 2] != text[0] || checksum[i * 2 + 1] != text[1])
- {
- return false;
- }
- }
-
- return true;
- }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/CompilationFailedException.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/CompilationFailedException.cs
deleted file mode 100644
index 5e3899c0b..000000000
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/CompilationFailedException.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-// 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.Linq;
-using Microsoft.AspNetCore.Diagnostics;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
-{
- ///
- /// An thrown when accessing the result of a failed compilation.
- ///
- public class CompilationFailedException : Exception, ICompilationException
- {
- ///
- /// Instantiates a new instance of .
- ///
- /// s containing
- /// details of the compilation failure.
- public CompilationFailedException(
- IEnumerable compilationFailures)
- : base(FormatMessage(compilationFailures))
- {
- if (compilationFailures == null)
- {
- throw new ArgumentNullException(nameof(compilationFailures));
- }
-
- CompilationFailures = compilationFailures;
- }
-
- ///
- public IEnumerable CompilationFailures { get; }
-
- private static string FormatMessage(IEnumerable compilationFailures)
- {
- return Resources.CompilationFailed + Environment.NewLine +
- string.Join(
- Environment.NewLine,
- compilationFailures.SelectMany(f => f.Messages).Select(message => message.FormattedMessage));
- }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/CompilationFailedExceptionFactory.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/CompilationFailedExceptionFactory.cs
deleted file mode 100644
index 324b83572..000000000
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/CompilationFailedExceptionFactory.cs
+++ /dev/null
@@ -1,157 +0,0 @@
-// 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.Linq;
-using Microsoft.AspNetCore.Diagnostics;
-using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
-{
- internal static class CompilationFailedExceptionFactory
- {
- // 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);
-
- public static CompilationFailedException Create(
- RazorCodeDocument codeDocument,
- IEnumerable diagnostics)
- {
- // If a SourceLocation does not specify a file path, assume it is produced from parsing the current file.
- var messageGroups = diagnostics.GroupBy(
- razorError => razorError.Span.FilePath ?? codeDocument.Source.FilePath,
- StringComparer.Ordinal);
-
- var failures = new List();
- foreach (var group in messageGroups)
- {
- var filePath = group.Key;
- var fileContent = ReadContent(codeDocument, filePath);
- var compilationFailure = new CompilationFailure(
- filePath,
- fileContent,
- compiledContent: string.Empty,
- messages: group.Select(parserError => CreateDiagnosticMessage(parserError, filePath)));
- failures.Add(compilationFailure);
- }
-
- return new CompilationFailedException(failures);
- }
-
- public static CompilationFailedException Create(
- RazorCodeDocument codeDocument,
- string compilationContent,
- string assemblyName,
- IEnumerable diagnostics)
- {
- var diagnosticGroups = diagnostics
- .Where(diagnostic => diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error)
- .GroupBy(diagnostic => GetFilePath(codeDocument, diagnostic), StringComparer.Ordinal);
-
- var failures = new List();
- foreach (var group in diagnosticGroups)
- {
- var sourceFilePath = group.Key;
- string sourceFileContent;
- if (string.Equals(assemblyName, sourceFilePath, StringComparison.Ordinal))
- {
- // The error is in the generated code and does not have a mapping line pragma
- sourceFileContent = compilationContent;
- sourceFilePath = Resources.GeneratedCodeFileName;
- }
- else
- {
- sourceFileContent = ReadContent(codeDocument, 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_MissingReferences(
- "CopyRefAssembliesToPublishDirectory");
- }
-
- var compilationFailure = new CompilationFailure(
- sourceFilePath,
- sourceFileContent,
- compilationContent,
- group.Select(GetDiagnosticMessage),
- additionalMessage);
-
- failures.Add(compilationFailure);
- }
-
- return new CompilationFailedException(failures);
- }
-
- private static string ReadContent(RazorCodeDocument codeDocument, string filePath)
- {
- RazorSourceDocument sourceDocument;
- if (string.IsNullOrEmpty(filePath) || string.Equals(codeDocument.Source.FilePath, filePath, StringComparison.Ordinal))
- {
- sourceDocument = codeDocument.Source;
- }
- else
- {
- sourceDocument = codeDocument.Imports.FirstOrDefault(f => string.Equals(f.FilePath, filePath, StringComparison.Ordinal));
- }
-
- if (sourceDocument != null)
- {
- var contentChars = new char[sourceDocument.Length];
- sourceDocument.CopyTo(0, contentChars, 0, sourceDocument.Length);
- return new string(contentChars);
- }
-
- return string.Empty;
- }
-
- private static DiagnosticMessage GetDiagnosticMessage(Diagnostic diagnostic)
- {
- var mappedLineSpan = diagnostic.Location.GetMappedLineSpan();
- return new DiagnosticMessage(
- diagnostic.GetMessage(),
- CSharpDiagnosticFormatter.Instance.Format(diagnostic),
- mappedLineSpan.Path,
- mappedLineSpan.StartLinePosition.Line + 1,
- mappedLineSpan.StartLinePosition.Character + 1,
- mappedLineSpan.EndLinePosition.Line + 1,
- mappedLineSpan.EndLinePosition.Character + 1);
- }
-
- private static DiagnosticMessage CreateDiagnosticMessage(
- RazorDiagnostic razorDiagnostic,
- string filePath)
- {
- var sourceSpan = razorDiagnostic.Span;
- var message = razorDiagnostic.GetMessage();
- return new DiagnosticMessage(
- message: message,
- formattedMessage: razorDiagnostic.ToString(),
- filePath: filePath,
- startLine: sourceSpan.LineIndex + 1,
- startColumn: sourceSpan.CharacterIndex,
- endLine: sourceSpan.LineIndex + 1,
- endColumn: sourceSpan.CharacterIndex + sourceSpan.Length);
- }
-
- private static string GetFilePath(RazorCodeDocument codeDocument, Diagnostic diagnostic)
- {
- if (diagnostic.Location == Location.None)
- {
- return codeDocument.Source.FilePath;
- }
-
- return diagnostic.Location.GetMappedLineSpan().Path;
- }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/CompiledViewDescriptor.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/CompiledViewDescriptor.cs
index 1e5bbb0c4..213218c5c 100644
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/CompiledViewDescriptor.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/CompiledViewDescriptor.cs
@@ -51,7 +51,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
// later.
ExpirationTokens = Array.Empty();
RelativePath = ViewPath.NormalizePath(item?.Identifier ?? attribute.Path);
- IsPrecompiled = true;
}
///
@@ -72,11 +71,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
///
public IList ExpirationTokens { get; set; }
- ///
- /// Gets a value that determines if the view is precompiled.
- ///
- public bool IsPrecompiled { get; set; }
-
///
/// Gets the descriptor for this view.
///
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/DefaultRazorPageFactoryProvider.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/DefaultRazorPageFactoryProvider.cs
index a96874988..fc0d03cf0 100644
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/DefaultRazorPageFactoryProvider.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/DefaultRazorPageFactoryProvider.cs
@@ -4,7 +4,6 @@
using System;
using System.Linq.Expressions;
using System.Reflection;
-using Microsoft.AspNetCore.Mvc.Razor.Compilation;
namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
{
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/DefaultRazorReferenceManager.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/DefaultRazorReferenceManager.cs
deleted file mode 100644
index b2a8e8012..000000000
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/DefaultRazorReferenceManager.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-// 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.Linq;
-using System.Threading;
-using Microsoft.AspNetCore.Mvc.ApplicationParts;
-using Microsoft.CodeAnalysis;
-using Microsoft.Extensions.Options;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
-{
-#pragma warning disable CS0618 // Type or member is obsolete
- internal class DefaultRazorReferenceManager : RazorReferenceManager
-#pragma warning restore CS0618 // Type or member is obsolete
- {
- private readonly ApplicationPartManager _partManager;
- private readonly IList _additionalMetadataReferences;
- private object _compilationReferencesLock = new object();
- private bool _compilationReferencesInitialized;
- private IReadOnlyList _compilationReferences;
-
- public DefaultRazorReferenceManager(
- ApplicationPartManager partManager,
- IOptions optionsAccessor)
- {
- _partManager = partManager;
-#pragma warning disable CS0618 // Type or member is obsolete
- _additionalMetadataReferences = optionsAccessor.Value.AdditionalCompilationReferences;
-#pragma warning restore CS0618 // Type or member is obsolete
- }
-
- public override IReadOnlyList CompilationReferences
- {
- get
- {
- return LazyInitializer.EnsureInitialized(
- ref _compilationReferences,
- ref _compilationReferencesInitialized,
- ref _compilationReferencesLock,
- GetCompilationReferences);
- }
- }
-
- private IReadOnlyList GetCompilationReferences()
- {
-#pragma warning disable CS0618 // Type or member is obsolete
- var feature = new MetadataReferenceFeature();
-#pragma warning restore CS0618 // Type or member is obsolete
- _partManager.PopulateFeature(feature);
- var applicationReferences = feature.MetadataReferences;
-
- if (_additionalMetadataReferences.Count == 0)
- {
- return applicationReferences.ToArray();
- }
-
- var compilationReferences = new List(applicationReferences.Count + _additionalMetadataReferences.Count);
- compilationReferences.AddRange(applicationReferences);
- compilationReferences.AddRange(_additionalMetadataReferences);
-
- return compilationReferences;
- }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/ExpressionRewriter.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/ExpressionRewriter.cs
deleted file mode 100644
index d76b635d3..000000000
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/ExpressionRewriter.cs
+++ /dev/null
@@ -1,215 +0,0 @@
-// 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.Diagnostics;
-using System.Linq.Expressions;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
-{
- ///
- /// An expression rewriter which can hoist a simple expression lambda into a private field.
- ///
- internal class ExpressionRewriter : CSharpSyntaxRewriter
- {
- private static readonly string FieldNameTemplate = "__h{0}";
-
- public ExpressionRewriter(SemanticModel semanticModel)
- {
- SemanticModel = semanticModel;
-
- Expressions = new List>();
- }
-
- // We only want to rewrite expressions for the top-level class definition.
- private bool IsInsideClass { get; set; }
-
- private SemanticModel SemanticModel { get; }
-
- private List> Expressions { get; }
-
- public static CSharpCompilation Rewrite(CSharpCompilation compilation)
- {
- var rewrittenTrees = new List();
- foreach (var tree in compilation.SyntaxTrees)
- {
- var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true);
- var rewriter = new ExpressionRewriter(semanticModel);
-
- var rewrittenTree = tree.WithRootAndOptions(rewriter.Visit(tree.GetRoot()), tree.Options);
- rewrittenTrees.Add(rewrittenTree);
- }
-
- return compilation.RemoveAllSyntaxTrees().AddSyntaxTrees(rewrittenTrees);
- }
-
- public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
- {
- if (IsInsideClass)
- {
- // Avoid recursing into nested classes.
- return node;
- }
-
- Expressions.Clear();
-
- IsInsideClass = true;
-
- // Call base first to visit all the children and populate Expressions.
- var classDeclaration = (ClassDeclarationSyntax)base.VisitClassDeclaration(node);
-
- IsInsideClass = false;
-
- var memberDeclarations = new List();
- foreach (var kvp in Expressions)
- {
- var expression = kvp.Key;
- var memberName = kvp.Value.GetFirstToken();
-
- var expressionType = SemanticModel.GetTypeInfo(expression).ConvertedType;
- var declaration = SyntaxFactory.FieldDeclaration(
- SyntaxFactory.List(),
- SyntaxFactory.TokenList(
- SyntaxFactory.Token(SyntaxKind.PrivateKeyword),
- SyntaxFactory.Token(SyntaxKind.StaticKeyword),
- SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword)),
- SyntaxFactory.VariableDeclaration(
- SyntaxFactory.ParseTypeName(expressionType.ToDisplayString(
- SymbolDisplayFormat.FullyQualifiedFormat)),
- SyntaxFactory.SingletonSeparatedList(
- SyntaxFactory.VariableDeclarator(
- memberName,
- SyntaxFactory.BracketedArgumentList(),
- SyntaxFactory.EqualsValueClause(expression)))))
- .WithTriviaFrom(expression);
- memberDeclarations.Add(declaration);
- }
-
- return classDeclaration.AddMembers(memberDeclarations.ToArray());
- }
-
- public override SyntaxNode VisitSimpleLambdaExpression(SimpleLambdaExpressionSyntax node)
- {
- Debug.Assert(IsInsideClass);
-
- // If this lambda is an Expression and is suitable for hoisting, we rewrite this into a field access.
- //
- // Before:
- // public Task ExecuteAsync(...)
- // {
- // ...
- // Html.EditorFor(m => m.Price);
- // ...
- // }
- //
- //
- // After:
- // private static readonly Expression> __h0 = m => m.Price;
- // public Task ExecuteAsync(...)
- // {
- // ...
- // Html.EditorFor(__h0);
- // ...
- // }
- //
- var type = SemanticModel.GetTypeInfo(node);
-
- // Due to an anomaly where Roslyn (depending on code sample) may finish compilation without diagnostic
- // errors (this code path does not execute when diagnostic errors are present) we need to validate that
- // the ConvertedType was determined/is not null.
- if (type.ConvertedType == null ||
- type.ConvertedType.Name != typeof(Expression).Name &&
- type.ConvertedType.ContainingNamespace.Name != typeof(Expression).Namespace)
- {
- return node;
- }
-
- if (!node.Parent.IsKind(SyntaxKind.Argument))
- {
- return node;
- }
-
- var parameter = node.Parameter;
- if (IsValidForHoisting(parameter, node.Body))
- {
- // Replace with a MemberAccess
- var memberName = string.Format(FieldNameTemplate, Expressions.Count);
- var memberAccess = PadMemberAccess(node, SyntaxFactory.IdentifierName(memberName));
- Expressions.Add(new KeyValuePair(node, memberAccess));
- return memberAccess;
- }
-
- return node;
- }
-
- private static IdentifierNameSyntax PadMemberAccess(
- SimpleLambdaExpressionSyntax node,
- IdentifierNameSyntax memberAccess)
- {
- var charactersToExclude = memberAccess.Identifier.Text.Length;
- var triviaList = new SyntaxTriviaList();
-
- // Go through each token and
- // 1. Append leading trivia
- // 2. Append the same number of whitespace as the length of the token text
- // 3. Append trailing trivia
- foreach (var token in node.DescendantTokens())
- {
- if (token.HasLeadingTrivia)
- {
- triviaList = triviaList.AddRange(token.LeadingTrivia);
- }
-
- // Need to exclude the length of the member name from the padding.
- var padding = token.Text.Length;
- if (padding > charactersToExclude)
- {
- padding -= charactersToExclude;
- charactersToExclude = 0;
- }
- else
- {
- charactersToExclude -= padding;
- padding = 0;
- }
-
- if (padding > 0)
- {
- triviaList = triviaList.Add(SyntaxFactory.Whitespace(new string(' ', padding)));
- }
-
- if (token.HasTrailingTrivia)
- {
- triviaList = triviaList.AddRange(token.TrailingTrivia);
- }
- }
-
- return memberAccess
- .WithLeadingTrivia(node.GetLeadingTrivia())
- .WithTrailingTrivia(triviaList);
- }
-
- private static bool IsValidForHoisting(ParameterSyntax parameter, CSharpSyntaxNode node)
- {
- if (node.IsKind(SyntaxKind.IdentifierName))
- {
- var identifier = (IdentifierNameSyntax)node;
- if (identifier.Identifier.Text == parameter.Identifier.Text)
- {
- return true;
- }
- }
- else if (node.IsKind(SyntaxKind.SimpleMemberAccessExpression))
- {
- var memberAccess = (MemberAccessExpressionSyntax)node;
- var lhs = memberAccess.Expression;
- return IsValidForHoisting(parameter, lhs);
- }
-
- return false;
- }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/IViewCompilationMemoryCacheProvider.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/IViewCompilationMemoryCacheProvider.cs
deleted file mode 100644
index 5abbd550f..000000000
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/IViewCompilationMemoryCacheProvider.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-// 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 Microsoft.Extensions.Caching.Memory;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
-{
- ///
- /// Provides an instance of that is used to store compiled Razor views.
- ///
- public interface IViewCompilationMemoryCacheProvider
- {
- IMemoryCache CompilationMemoryCache { get; }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/MetadataReferenceFeature.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/MetadataReferenceFeature.cs
deleted file mode 100644
index 478d21eed..000000000
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/MetadataReferenceFeature.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-// 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 Microsoft.CodeAnalysis;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
-{
- ///
- /// Specifies the list of used in Razor compilation.
- ///
- [Obsolete("This type is obsolete and will be removed in a future version. See https://aka.ms/AA1x4gg for details.")]
- 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
deleted file mode 100644
index 8050671a1..000000000
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/MetadataReferenceFeatureProvider.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-// 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
- /// .
- ///
- [Obsolete("This type is obsolete and will be removed in a future version. See https://aka.ms/AA1x4gg for details.")]
- 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 referencePaths = providerPart.GetReferencePaths();
- 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/Compilation/RazorReferenceManager.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/RazorReferenceManager.cs
deleted file mode 100644
index df0962316..000000000
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/RazorReferenceManager.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-// 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 Microsoft.CodeAnalysis;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
-{
- ///
- /// Manages compilation references for Razor compilation.
- ///
- [Obsolete("This type is obsolete and will be removed in a future version. See https://aka.ms/AA1x4gg for details.")]
- public abstract class RazorReferenceManager
- {
- ///
- /// Gets the set of compilation references to be used for Razor compilation.
- ///
- public abstract IReadOnlyList CompilationReferences { get; }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/RazorViewCompilationMemoryCacheProvider.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/RazorViewCompilationMemoryCacheProvider.cs
deleted file mode 100644
index 9a11db0b3..000000000
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/RazorViewCompilationMemoryCacheProvider.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-// 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 Microsoft.Extensions.Caching.Memory;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
-{
- internal class RazorViewCompilationMemoryCacheProvider : IViewCompilationMemoryCacheProvider
- {
- IMemoryCache IViewCompilationMemoryCacheProvider.CompilationMemoryCache { get; } = new MemoryCache(new MemoryCacheOptions());
- }
-}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/RazorViewCompiler.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/RazorViewCompiler.cs
index 8dbc2012f..7afc53eda 100644
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/RazorViewCompiler.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/RazorViewCompiler.cs
@@ -5,18 +5,7 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Text;
using System.Threading.Tasks;
-using Microsoft.AspNetCore.Razor.Hosting;
-using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.Emit;
-using Microsoft.CodeAnalysis.Text;
-using Microsoft.Extensions.Caching.Memory;
-using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives;
@@ -27,48 +16,17 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
///
internal class RazorViewCompiler : IViewCompiler
{
- private readonly object _cacheLock = new object();
- private readonly Dictionary _precompiledViews;
+ private readonly Dictionary> _compiledViews;
private readonly ConcurrentDictionary _normalizedPathCache;
- private readonly IFileProvider _fileProvider;
- private readonly RazorProjectEngine _projectEngine;
- private readonly Action _compilationCallback;
- private readonly IMemoryCache _cache;
private readonly ILogger _logger;
- private readonly CSharpCompiler _csharpCompiler;
public RazorViewCompiler(
- IFileProvider fileProvider,
- RazorProjectEngine projectEngine,
- CSharpCompiler csharpCompiler,
- Action compilationCallback,
- IList precompiledViews,
- IMemoryCache cache,
+ IList compiledViews,
ILogger logger)
{
- if (fileProvider == null)
+ if (compiledViews == null)
{
- throw new ArgumentNullException(nameof(fileProvider));
- }
-
- if (projectEngine == null)
- {
- throw new ArgumentNullException(nameof(projectEngine));
- }
-
- if (csharpCompiler == null)
- {
- throw new ArgumentNullException(nameof(csharpCompiler));
- }
-
- if (compilationCallback == null)
- {
- throw new ArgumentNullException(nameof(compilationCallback));
- }
-
- if (precompiledViews == null)
- {
- throw new ArgumentNullException(nameof(precompiledViews));
+ throw new ArgumentNullException(nameof(compiledViews));
}
if (logger == null)
@@ -76,47 +34,35 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
throw new ArgumentNullException(nameof(logger));
}
- _fileProvider = fileProvider;
- _projectEngine = projectEngine;
- _csharpCompiler = csharpCompiler;
- _compilationCallback = compilationCallback;
_logger = logger;
-
-
_normalizedPathCache = new ConcurrentDictionary(StringComparer.Ordinal);
- // This is our L0 cache, and is a durable store. Views migrate into the cache as they are requested
- // from either the set of known precompiled views, or by being compiled.
- _cache = cache;
-
// We need to validate that the all of the precompiled views are unique by path (case-insensitive).
// We do this because there's no good way to canonicalize paths on windows, and it will create
// problems when deploying to linux. Rather than deal with these issues, we just don't support
// views that differ only by case.
- _precompiledViews = new Dictionary(
- precompiledViews.Count,
+ _compiledViews = new Dictionary>(
+ compiledViews.Count,
StringComparer.OrdinalIgnoreCase);
- foreach (var precompiledView in precompiledViews)
+ foreach (var compiledView in compiledViews)
{
- logger.ViewCompilerLocatedCompiledView(precompiledView.RelativePath);
+ logger.ViewCompilerLocatedCompiledView(compiledView.RelativePath);
- if (!_precompiledViews.ContainsKey(precompiledView.RelativePath))
+ if (!_compiledViews.ContainsKey(compiledView.RelativePath))
{
- // View ordering has precedence semantics, a view with a higher precedence was
+ // View ordering has precedence semantics, a view with a higher precedence was not
// already added to the list.
- _precompiledViews.Add(precompiledView.RelativePath, precompiledView);
+ _compiledViews.Add(compiledView.RelativePath, Task.FromResult(compiledView));
}
}
- if (_precompiledViews.Count == 0)
+ if (_compiledViews.Count == 0)
{
logger.ViewCompilerNoCompiledViewsFound();
}
}
- public bool AllowRecompilingViewsOnFileChange { get; set; }
-
///
public Task CompileAsync(string relativePath)
{
@@ -127,320 +73,26 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
// Attempt to lookup the cache entry using the passed in path. This will succeed if the path is already
// normalized and a cache entry exists.
- if (_cache.TryGetValue(relativePath, out Task cachedResult))
+ if (_compiledViews.TryGetValue(relativePath, out var cachedResult))
{
+ _logger.ViewCompilerLocatedCompiledViewForPath(relativePath);
return cachedResult;
}
var normalizedPath = GetNormalizedPath(relativePath);
- if (_cache.TryGetValue(normalizedPath, out cachedResult))
+ if (_compiledViews.TryGetValue(normalizedPath, out cachedResult))
{
+ _logger.ViewCompilerLocatedCompiledViewForPath(normalizedPath);
return cachedResult;
}
// Entry does not exist. Attempt to create one.
- cachedResult = OnCacheMiss(normalizedPath);
- return cachedResult;
- }
-
- private Task OnCacheMiss(string normalizedPath)
- {
- ViewCompilerWorkItem item;
- TaskCompletionSource taskSource;
- MemoryCacheEntryOptions cacheEntryOptions;
-
- // Safe races cannot be allowed when compiling Razor pages. To ensure only one compilation request succeeds
- // per file, we'll lock the creation of a cache entry. Creating the cache entry should be very quick. The
- // actual work for compiling files happens outside the critical section.
- lock (_cacheLock)
+ _logger.ViewCompilerCouldNotFindFileAtPath(relativePath);
+ return Task.FromResult(new CompiledViewDescriptor
{
- // Double-checked locking to handle a possible race.
- if (_cache.TryGetValue(normalizedPath, out Task result))
- {
- return result;
- }
-
- if (_precompiledViews.TryGetValue(normalizedPath, out var precompiledView))
- {
- _logger.ViewCompilerLocatedCompiledViewForPath(normalizedPath);
- item = CreatePrecompiledWorkItem(normalizedPath, precompiledView);
- }
- else
- {
- item = CreateRuntimeCompilationWorkItem(normalizedPath);
- }
-
- // At this point, we've decided what to do - but we should create the cache entry and
- // release the lock first.
- cacheEntryOptions = new MemoryCacheEntryOptions();
-
- Debug.Assert(item.ExpirationTokens != null);
- for (var i = 0; i < item.ExpirationTokens.Count; i++)
- {
- cacheEntryOptions.ExpirationTokens.Add(item.ExpirationTokens[i]);
- }
-
- taskSource = new TaskCompletionSource(creationOptions: TaskCreationOptions.RunContinuationsAsynchronously);
- if (item.SupportsCompilation)
- {
- // We'll compile in just a sec, be patient.
- }
- else
- {
- // If we can't compile, we should have already created the descriptor
- Debug.Assert(item.Descriptor != null);
- taskSource.SetResult(item.Descriptor);
- }
-
- _cache.Set(normalizedPath, taskSource.Task, cacheEntryOptions);
- }
-
- // Now the lock has been released so we can do more expensive processing.
- if (item.SupportsCompilation)
- {
- Debug.Assert(taskSource != null);
-
- if (item.Descriptor?.Item != null &&
- ChecksumValidator.IsItemValid(_projectEngine.FileSystem, item.Descriptor.Item))
- {
- // If the item has checksums to validate, we should also have a precompiled view.
- Debug.Assert(item.Descriptor != null);
-
- taskSource.SetResult(item.Descriptor);
- return taskSource.Task;
- }
-
- _logger.ViewCompilerInvalidingCompiledFile(item.NormalizedPath);
- try
- {
- var descriptor = CompileAndEmit(normalizedPath);
- descriptor.ExpirationTokens = cacheEntryOptions.ExpirationTokens;
- taskSource.SetResult(descriptor);
- }
- catch (Exception ex)
- {
- taskSource.SetException(ex);
- }
- }
-
- return taskSource.Task;
- }
-
- private ViewCompilerWorkItem CreatePrecompiledWorkItem(string normalizedPath, CompiledViewDescriptor precompiledView)
- {
- // We have a precompiled view - but we're not sure that we can use it yet.
- //
- // We need to determine first if we have enough information to 'recompile' this view. If that's the case
- // we'll create change tokens for all of the files.
- //
- // Then we'll attempt to validate if any of those files have different content than the original sources
- // based on checksums.
- if (precompiledView.Item == null || !ChecksumValidator.IsRecompilationSupported(precompiledView.Item))
- {
- return new ViewCompilerWorkItem()
- {
- // If we don't have a checksum for the primary source file we can't recompile.
- SupportsCompilation = false,
-
- ExpirationTokens = Array.Empty(), // Never expire because we can't recompile.
- Descriptor = precompiledView, // This will be used as-is.
- };
- }
-
- var item = new ViewCompilerWorkItem()
- {
- SupportsCompilation = true,
-
- Descriptor = precompiledView, // This might be used, if the checksums match.
-
- // Used to validate and recompile
- NormalizedPath = normalizedPath,
-
- ExpirationTokens = GetExpirationTokens(precompiledView),
- };
-
- // We also need to create a new descriptor, because the original one doesn't have expiration tokens on
- // it. These will be used by the view location cache, which is like an L1 cache for views (this class is
- // the L2 cache).
- item.Descriptor = new CompiledViewDescriptor()
- {
- ExpirationTokens = item.ExpirationTokens,
- IsPrecompiled = true,
- Item = precompiledView.Item,
- RelativePath = precompiledView.RelativePath,
- ViewAttribute = precompiledView.ViewAttribute,
- };
-
- return item;
- }
-
- private ViewCompilerWorkItem CreateRuntimeCompilationWorkItem(string normalizedPath)
- {
- IList expirationTokens = Array.Empty();
-
- if (AllowRecompilingViewsOnFileChange)
- {
- var changeToken = _fileProvider.Watch(normalizedPath);
- expirationTokens = new List { changeToken };
- }
-
- var projectItem = _projectEngine.FileSystem.GetItem(normalizedPath);
- if (!projectItem.Exists)
- {
- _logger.ViewCompilerCouldNotFindFileAtPath(normalizedPath);
-
- // If the file doesn't exist, we can't do compilation right now - we still want to cache
- // the fact that we tried. This will allow us to re-trigger compilation if the view file
- // is added.
- return new ViewCompilerWorkItem()
- {
- // We don't have enough information to compile
- SupportsCompilation = false,
-
- Descriptor = new CompiledViewDescriptor()
- {
- RelativePath = normalizedPath,
- ExpirationTokens = expirationTokens,
- },
-
- // We can try again if the file gets created.
- ExpirationTokens = expirationTokens,
- };
- }
-
- _logger.ViewCompilerFoundFileToCompile(normalizedPath);
-
- GetChangeTokensFromImports(expirationTokens, projectItem);
-
- return new ViewCompilerWorkItem()
- {
- SupportsCompilation = true,
-
- NormalizedPath = normalizedPath,
- ExpirationTokens = expirationTokens,
- };
- }
-
- private IList GetExpirationTokens(CompiledViewDescriptor precompiledView)
- {
- if (!AllowRecompilingViewsOnFileChange)
- {
- return Array.Empty();
- }
-
- var checksums = precompiledView.Item.GetChecksumMetadata();
- var expirationTokens = new List(checksums.Count);
-
- for (var i = 0; i < checksums.Count; i++)
- {
- // We rely on Razor to provide the right set of checksums. Trust the compiler, it has to do a good job,
- // so it probably will.
- expirationTokens.Add(_fileProvider.Watch(checksums[i].Identifier));
- }
-
- return expirationTokens;
- }
-
- private void GetChangeTokensFromImports(IList expirationTokens, RazorProjectItem projectItem)
- {
- if (!AllowRecompilingViewsOnFileChange)
- {
- return;
- }
-
- // OK this means we can do compilation. For now let's just identify the other files we need to watch
- // so we can create the cache entry. Compilation will happen after we release the lock.
- var importFeature = _projectEngine.ProjectFeatures.OfType().FirstOrDefault();
-
- // There should always be an import feature unless someone has misconfigured their RazorProjectEngine.
- // In that case once we attempt to parse the Razor file we'll explode and give the a user a decent
- // error message; for now, lets just be extra protective and assume 0 imports to not give a bad error.
- var imports = importFeature?.GetImports(projectItem) ?? Enumerable.Empty();
- var physicalImports = imports.Where(import => import.FilePath != null);
-
- // Now that we have non-dynamic imports we need to get their RazorProjectItem equivalents so we have their
- // physical file paths (according to the FileSystem).
- foreach (var physicalImport in physicalImports)
- {
- expirationTokens.Add(_fileProvider.Watch(physicalImport.FilePath));
- }
- }
-
- protected virtual CompiledViewDescriptor CompileAndEmit(string relativePath)
- {
- var projectItem = _projectEngine.FileSystem.GetItem(relativePath);
- var codeDocument = _projectEngine.Process(projectItem);
- var cSharpDocument = codeDocument.GetCSharpDocument();
-
- if (cSharpDocument.Diagnostics.Count > 0)
- {
- throw CompilationFailedExceptionFactory.Create(
- codeDocument,
- cSharpDocument.Diagnostics);
- }
-
- var assembly = CompileAndEmit(codeDocument, cSharpDocument.GeneratedCode);
-
- // Anything we compile from source will use Razor 2.1 and so should have the new metadata.
- var loader = new RazorCompiledItemLoader();
- var item = loader.LoadItems(assembly).SingleOrDefault();
- var attribute = assembly.GetCustomAttribute();
-
- return new CompiledViewDescriptor(item, attribute);
- }
-
- internal Assembly CompileAndEmit(RazorCodeDocument codeDocument, string generatedCode)
- {
- _logger.GeneratedCodeToAssemblyCompilationStart(codeDocument.Source.FilePath);
-
- var startTimestamp = _logger.IsEnabled(LogLevel.Debug) ? Stopwatch.GetTimestamp() : 0;
-
- var assemblyName = Path.GetRandomFileName();
- var compilation = CreateCompilation(generatedCode, assemblyName);
-
- var emitOptions = _csharpCompiler.EmitOptions;
- var emitPdbFile = _csharpCompiler.EmitPdb && emitOptions.DebugInformationFormat != DebugInformationFormat.Embedded;
-
- using (var assemblyStream = new MemoryStream())
- using (var pdbStream = emitPdbFile ? new MemoryStream() : null)
- {
- var result = compilation.Emit(
- assemblyStream,
- pdbStream,
- options: emitOptions);
-
- if (!result.Success)
- {
- throw CompilationFailedExceptionFactory.Create(
- codeDocument,
- generatedCode,
- assemblyName,
- result.Diagnostics);
- }
-
- assemblyStream.Seek(0, SeekOrigin.Begin);
- pdbStream?.Seek(0, SeekOrigin.Begin);
-
- var assembly = Assembly.Load(assemblyStream.ToArray(), pdbStream?.ToArray());
- _logger.GeneratedCodeToAssemblyCompilationEnd(codeDocument.Source.FilePath, startTimestamp);
-
- return assembly;
- }
- }
-
- private CSharpCompilation CreateCompilation(string compilationContent, string assemblyName)
- {
- var sourceText = SourceText.From(compilationContent, Encoding.UTF8);
- var syntaxTree = _csharpCompiler.CreateSyntaxTree(sourceText).WithFilePath(assemblyName);
- var compilation = _csharpCompiler
- .CreateCompilation(assemblyName)
- .AddSyntaxTrees(syntaxTree);
- compilation = ExpressionRewriter.Rewrite(compilation);
-
- var compilationContext = new RoslynCompilationContext(compilation);
- _compilationCallback(compilationContext);
- compilation = compilationContext.Compilation;
- return compilation;
+ RelativePath = normalizedPath,
+ ExpirationTokens = Array.Empty(),
+ });
}
private string GetNormalizedPath(string relativePath)
@@ -459,16 +111,5 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
return normalizedPath;
}
-
- private class ViewCompilerWorkItem
- {
- public bool SupportsCompilation { get; set; }
-
- public string NormalizedPath { get; set; }
-
- public IList ExpirationTokens { get; set; }
-
- public CompiledViewDescriptor Descriptor { get; set; }
- }
}
}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/RazorViewCompilerProvider.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/RazorViewCompilerProvider.cs
index 44fb8a0ef..64965e6f7 100644
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/RazorViewCompilerProvider.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/RazorViewCompilerProvider.cs
@@ -1,89 +1,25 @@
// 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.Threading;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
-using Microsoft.AspNetCore.Mvc.Razor.Compilation;
-using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
{
internal class RazorViewCompilerProvider : IViewCompilerProvider
{
- private readonly RazorProjectEngine _razorProjectEngine;
- private readonly ApplicationPartManager _applicationPartManager;
- private readonly IRazorViewEngineFileProviderAccessor _fileProviderAccessor;
- private readonly CSharpCompiler _csharpCompiler;
- private readonly IViewCompilationMemoryCacheProvider _compilationMemoryCacheProvider;
- private readonly RazorViewEngineOptions _viewEngineOptions;
- private readonly ILogger _logger;
- private readonly Func _createCompiler;
-
- private object _initializeLock = new object();
- private bool _initialized;
- private IViewCompiler _compiler;
+ private readonly RazorViewCompiler _compiler;
public RazorViewCompilerProvider(
ApplicationPartManager applicationPartManager,
- RazorProjectEngine razorProjectEngine,
- IRazorViewEngineFileProviderAccessor fileProviderAccessor,
- CSharpCompiler csharpCompiler,
- IOptions viewEngineOptionsAccessor,
- IViewCompilationMemoryCacheProvider compilationMemoryCacheProvider,
ILoggerFactory loggerFactory)
- {
- _applicationPartManager = applicationPartManager;
- _razorProjectEngine = razorProjectEngine;
- _fileProviderAccessor = fileProviderAccessor;
- _csharpCompiler = csharpCompiler;
- _compilationMemoryCacheProvider = compilationMemoryCacheProvider;
- _viewEngineOptions = viewEngineOptionsAccessor.Value;
-
- _logger = loggerFactory.CreateLogger();
- _createCompiler = CreateCompiler;
- }
-
- public IViewCompiler GetCompiler()
- {
- var fileProvider = _fileProviderAccessor.FileProvider;
- if (fileProvider is NullFileProvider)
- {
- var message = Resources.FormatFileProvidersAreRequired(
- typeof(RazorViewEngineOptions).FullName,
- nameof(RazorViewEngineOptions.FileProviders),
- typeof(IFileProvider).FullName);
- throw new InvalidOperationException(message);
- }
-
- return LazyInitializer.EnsureInitialized(
- ref _compiler,
- ref _initialized,
- ref _initializeLock,
- _createCompiler);
- }
-
- private IViewCompiler CreateCompiler()
{
var feature = new ViewsFeature();
- _applicationPartManager.PopulateFeature(feature);
+ applicationPartManager.PopulateFeature(feature);
- return new RazorViewCompiler(
- _fileProviderAccessor.FileProvider,
- _razorProjectEngine,
- _csharpCompiler,
-#pragma warning disable CS0618 // Type or member is obsolete
- _viewEngineOptions.CompilationCallback,
-#pragma warning restore CS0618 // Type or member is obsolete
- feature.ViewDescriptors,
- _compilationMemoryCacheProvider.CompilationMemoryCache,
- _logger)
- {
- AllowRecompilingViewsOnFileChange = _viewEngineOptions.AllowRecompilingViewsOnFileChange,
- };
+ _compiler = new RazorViewCompiler(feature.ViewDescriptors, loggerFactory.CreateLogger());
}
+
+ public IViewCompiler GetCompiler() => _compiler;
}
}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/RoslynCompilationContext.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/RoslynCompilationContext.cs
deleted file mode 100644
index 553696972..000000000
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/RoslynCompilationContext.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// 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 Microsoft.CodeAnalysis.CSharp;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
-{
- ///
- /// Context object used to pass information about the current Razor page compilation.
- ///
- public class RoslynCompilationContext
- {
- ///
- /// Constructs a new instance of the type.
- ///
- /// to be set to property.
- public RoslynCompilationContext(CSharpCompilation compilation)
- {
- if (compilation == null)
- {
- throw new ArgumentNullException(nameof(compilation));
- }
-
- Compilation = compilation;
- }
-
- ///
- /// Gets or sets the used for current source file compilation.
- ///
- public CSharpCompilation Compilation { get; set; }
- }
-}
\ No newline at end of file
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/SymbolsUtility.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/SymbolsUtility.cs
deleted file mode 100644
index bfe2b8841..000000000
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/SymbolsUtility.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-// 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.Runtime.InteropServices;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
-{
- ///
- /// Utility type for determining if a platform supports full pdb file generation.
- ///
- internal static class SymbolsUtility
- {
- // Native pdb writer's CLSID
- private const string SymWriterGuid = "0AE2DEB0-F901-478b-BB9F-881EE8066788";
-
- ///
- /// Determines if the current platform supports full pdb generation.
- ///
- /// true if full pdb generation is supported; false otherwise.
- public static bool SupportsFullPdbGeneration()
- {
- if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- {
- // Cross-plat always produce portable pdbs.
- return false;
- }
-
- if (Type.GetType("Mono.Runtime") != null)
- {
- return false;
- }
-
- try
- {
- // Check for the pdb writer component that roslyn uses to generate pdbs
- var type = Marshal.GetTypeFromCLSID(new Guid(SymWriterGuid));
- if (type != null)
- {
- // This line will throw if pdb generation is not supported.
- Activator.CreateInstance(type);
- return true;
- }
- }
- catch
- {
- }
-
- return false;
- }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/ViewsFeatureProvider.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/ViewsFeatureProvider.cs
index aebfe0008..911b01026 100644
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/ViewsFeatureProvider.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/ViewsFeatureProvider.cs
@@ -50,7 +50,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
ExpirationTokens = Array.Empty(),
RelativePath = relativePath,
ViewAttribute = attribute,
- IsPrecompiled = true,
};
feature.ViewDescriptors.Add(viewDescriptor);
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/DefaultRazorViewEngineFileProviderAccessor.cs b/src/Microsoft.AspNetCore.Mvc.Razor/DefaultRazorViewEngineFileProviderAccessor.cs
deleted file mode 100644
index 449527376..000000000
--- a/src/Microsoft.AspNetCore.Mvc.Razor/DefaultRazorViewEngineFileProviderAccessor.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-// 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 Microsoft.Extensions.FileProviders;
-using Microsoft.Extensions.Options;
-
-namespace Microsoft.AspNetCore.Mvc.Razor
-{
- ///
- /// Default implementation of .
- ///
- internal class DefaultRazorViewEngineFileProviderAccessor : IRazorViewEngineFileProviderAccessor
- {
- ///
- /// Initializes a new instance of .
- ///
- /// Accessor to .
- public DefaultRazorViewEngineFileProviderAccessor(IOptions optionsAccessor)
- {
- var fileProviders = optionsAccessor.Value.FileProviders;
- if (fileProviders.Count == 0)
- {
- FileProvider = new NullFileProvider();
- }
- else if (fileProviders.Count == 1)
- {
- FileProvider = fileProviders[0];
- }
- else
- {
- FileProvider = new CompositeFileProvider(fileProviders);
- }
- }
-
- ///
- /// Gets the used to look up Razor files.
- ///
- public IFileProvider FileProvider { get; }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/DependencyInjection/MvcRazorMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNetCore.Mvc.Razor/DependencyInjection/MvcRazorMvcCoreBuilderExtensions.cs
index c3f638825..46139a28a 100644
--- a/src/Microsoft.AspNetCore.Mvc.Razor/DependencyInjection/MvcRazorMvcCoreBuilderExtensions.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/DependencyInjection/MvcRazorMvcCoreBuilderExtensions.cs
@@ -2,26 +2,19 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
-using System.Diagnostics;
using System.Linq;
-using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
-using Microsoft.AspNetCore.Mvc.Razor.Extensions;
using Microsoft.AspNetCore.Mvc.Razor.Infrastructure;
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
-using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection.Extensions;
-using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
-using CompilationTagHelperFeature = Microsoft.CodeAnalysis.Razor.CompilationTagHelperFeature;
-using DefaultTagHelperDescriptorProvider = Microsoft.CodeAnalysis.Razor.DefaultTagHelperDescriptorProvider;
namespace Microsoft.Extensions.DependencyInjection
{
@@ -66,13 +59,6 @@ namespace Microsoft.Extensions.DependencyInjection
private static void AddRazorViewEngineFeatureProviders(IMvcCoreBuilder builder)
{
-#pragma warning disable CS0618 // Type or member is obsolete
- if (!builder.PartManager.FeatureProviders.OfType().Any())
- {
- builder.PartManager.FeatureProviders.Add(new MetadataReferenceFeatureProvider());
- }
-#pragma warning restore CS0618 // Type or member is obsolete
-
if (!builder.PartManager.FeatureProviders.OfType().Any())
{
builder.PartManager.FeatureProviders.Add(new TagHelperFeatureProvider());
@@ -148,74 +134,19 @@ namespace Microsoft.Extensions.DependencyInjection
// Internal for testing.
internal static void AddRazorViewEngineServices(IServiceCollection services)
{
- services.TryAddSingleton();
-#pragma warning disable CS0618 // Type or member is obsolete
- services.TryAddSingleton();
-#pragma warning restore CS0618 // Type or member is obsolete
-
services.TryAddEnumerable(
ServiceDescriptor.Transient, MvcRazorMvcViewOptionsSetup>());
services.TryAddEnumerable(
ServiceDescriptor.Transient, RazorViewEngineOptionsSetup>());
- services.TryAddEnumerable(
- ServiceDescriptor.Transient, RazorViewEngineOptionsSetup>());
-
- services.TryAddSingleton<
- IRazorViewEngineFileProviderAccessor,
- DefaultRazorViewEngineFileProviderAccessor>();
-
- services.TryAddSingleton(s =>
- {
- var pageFactory = s.GetRequiredService();
- var pageActivator = s.GetRequiredService();
- var htmlEncoder = s.GetRequiredService();
- var optionsAccessor = s.GetRequiredService>();
- var razorFileSystem = s.GetRequiredService();
- var loggerFactory = s.GetRequiredService();
- var diagnosticListener = s.GetRequiredService();
-
- var viewEngine = new RazorViewEngine(pageFactory, pageActivator, htmlEncoder, optionsAccessor, razorFileSystem, loggerFactory, diagnosticListener);
- return viewEngine;
- });
+ services.TryAddSingleton();
services.TryAddSingleton();
- services.TryAddSingleton();
// In the default scenario the following services are singleton by virtue of being initialized as part of
// creating the singleton RazorViewEngine instance.
services.TryAddTransient();
- //
- // Razor compilation infrastructure
- //
- services.TryAddSingleton();
- services.TryAddSingleton();
- services.TryAddSingleton(s =>
- {
- var fileSystem = s.GetRequiredService();
- var projectEngine = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem, builder =>
- {
- RazorExtensions.Register(builder);
-
- // Roslyn + TagHelpers infrastructure
- var metadataReferenceFeature = s.GetRequiredService();
- builder.Features.Add(metadataReferenceFeature);
- builder.Features.Add(new CompilationTagHelperFeature());
-
- // TagHelperDescriptorProviders (actually do tag helper discovery)
- builder.Features.Add(new DefaultTagHelperDescriptorProvider());
- builder.Features.Add(new ViewComponentTagHelperDescriptorProvider());
- });
-
- return projectEngine;
- });
-
- // Legacy Razor compilation services
- services.TryAddSingleton(s => s.GetRequiredService().FileSystem);
- services.TryAddSingleton();
- services.TryAddSingleton(s => s.GetRequiredService().Engine);
-
// This caches Razor page activation details that are valid for the lifetime of the application.
services.TryAddSingleton();
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/FileProviderRazorProject.cs b/src/Microsoft.AspNetCore.Mvc.Razor/FileProviderRazorProject.cs
deleted file mode 100644
index cde9cf1da..000000000
--- a/src/Microsoft.AspNetCore.Mvc.Razor/FileProviderRazorProject.cs
+++ /dev/null
@@ -1,91 +0,0 @@
-// 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 Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.Extensions.FileProviders;
-
-namespace Microsoft.AspNetCore.Mvc.Razor
-{
- internal class FileProviderRazorProjectFileSystem : RazorProjectFileSystem
- {
- private const string RazorFileExtension = ".cshtml";
- private readonly IFileProvider _provider;
- private readonly IHostingEnvironment _hostingEnvironment;
-
- public FileProviderRazorProjectFileSystem(IRazorViewEngineFileProviderAccessor accessor, IHostingEnvironment hostingEnvironment)
- {
- if (accessor == null)
- {
- throw new ArgumentNullException(nameof(accessor));
- }
-
- if (hostingEnvironment == null)
- {
- throw new ArgumentNullException(nameof(hostingEnvironment));
- }
-
- _provider = accessor.FileProvider;
- _hostingEnvironment = hostingEnvironment;
- }
-
- public override RazorProjectItem GetItem(string path)
- {
- path = NormalizeAndEnsureValidPath(path);
- var fileInfo = _provider.GetFileInfo(path);
-
- return new FileProviderRazorProjectItem(fileInfo, basePath: string.Empty, filePath: path, root: _hostingEnvironment.ContentRootPath);
- }
-
- public override IEnumerable EnumerateItems(string path)
- {
- path = NormalizeAndEnsureValidPath(path);
- return EnumerateFiles(_provider.GetDirectoryContents(path), path, prefix: string.Empty);
- }
-
- private IEnumerable EnumerateFiles(IDirectoryContents directory, string basePath, string prefix)
- {
- if (directory.Exists)
- {
- foreach (var fileInfo in directory)
- {
- if (fileInfo.IsDirectory)
- {
- var relativePath = prefix + "/" + fileInfo.Name;
- var subDirectory = _provider.GetDirectoryContents(JoinPath(basePath, relativePath));
- var children = EnumerateFiles(subDirectory, basePath, relativePath);
- foreach (var child in children)
- {
- yield return child;
- }
- }
- else if (string.Equals(RazorFileExtension, Path.GetExtension(fileInfo.Name), StringComparison.OrdinalIgnoreCase))
- {
- var filePath = prefix + "/" + fileInfo.Name;
-
- yield return new FileProviderRazorProjectItem(fileInfo, basePath, filePath: filePath, root: _hostingEnvironment.ContentRootPath);
- }
- }
- }
- }
-
- private static string JoinPath(string path1, string path2)
- {
- var hasTrailingSlash = path1.EndsWith("/", StringComparison.Ordinal);
- var hasLeadingSlash = path2.StartsWith("/", StringComparison.Ordinal);
- if (hasLeadingSlash && hasTrailingSlash)
- {
- return path1 + path2.Substring(1);
- }
- else if (hasLeadingSlash || hasTrailingSlash)
- {
- return path1 + path2;
- }
-
- return path1 + "/" + path2;
- }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/FileProviderRazorProjectItem.cs b/src/Microsoft.AspNetCore.Mvc.Razor/FileProviderRazorProjectItem.cs
deleted file mode 100644
index 5eb9f24b3..000000000
--- a/src/Microsoft.AspNetCore.Mvc.Razor/FileProviderRazorProjectItem.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-// 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.IO;
-using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.Extensions.FileProviders;
-
-namespace Microsoft.AspNetCore.Mvc.Razor
-{
- internal class FileProviderRazorProjectItem : RazorProjectItem
- {
- private string _root;
- private string _relativePhysicalPath;
- private bool _isRelativePhysicalPathSet;
-
- public FileProviderRazorProjectItem(IFileInfo fileInfo, string basePath, string filePath, string root)
- {
- FileInfo = fileInfo;
- BasePath = basePath;
- FilePath = filePath;
- _root = root;
- }
-
- public IFileInfo FileInfo { get; }
-
- public override string BasePath { get; }
-
- public override string FilePath { get; }
-
- public override bool Exists => FileInfo.Exists;
-
- public override string PhysicalPath => FileInfo.PhysicalPath;
-
- public override string RelativePhysicalPath
- {
- get
- {
- if (!_isRelativePhysicalPathSet)
- {
- _isRelativePhysicalPathSet = true;
-
- if (Exists)
- {
- if (_root != null &&
- !string.IsNullOrEmpty(PhysicalPath) &&
- PhysicalPath.StartsWith(_root, StringComparison.OrdinalIgnoreCase) &&
- PhysicalPath.Length > _root.Length &&
- (PhysicalPath[_root.Length] == Path.DirectorySeparatorChar || PhysicalPath[_root.Length] == Path.AltDirectorySeparatorChar))
- {
- _relativePhysicalPath = PhysicalPath.Substring(_root.Length + 1); // Include leading separator
- }
- }
- }
-
- return _relativePhysicalPath;
- }
- }
-
- public override Stream Read()
- {
- return FileInfo.CreateReadStream();
- }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/IRazorViewEngineFileProviderAccessor.cs b/src/Microsoft.AspNetCore.Mvc.Razor/IRazorViewEngineFileProviderAccessor.cs
deleted file mode 100644
index 19c5fde0c..000000000
--- a/src/Microsoft.AspNetCore.Mvc.Razor/IRazorViewEngineFileProviderAccessor.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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 Microsoft.Extensions.FileProviders;
-
-namespace Microsoft.AspNetCore.Mvc.Razor
-{
- ///
- /// Accessor to the used by .
- ///
- internal interface IRazorViewEngineFileProviderAccessor
- {
- ///
- /// Gets the used to look up Razor files.
- ///
- IFileProvider FileProvider { get; }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/LazyMetadataReferenceFeature.cs b/src/Microsoft.AspNetCore.Mvc.Razor/LazyMetadataReferenceFeature.cs
deleted file mode 100644
index a7b86b00f..000000000
--- a/src/Microsoft.AspNetCore.Mvc.Razor/LazyMetadataReferenceFeature.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// 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.AspNetCore.Razor.Language;
-using Microsoft.AspNetCore.Mvc.Razor.Compilation;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.Razor;
-
-namespace Microsoft.AspNetCore.Mvc.Razor
-{
- internal class LazyMetadataReferenceFeature : IMetadataReferenceFeature
- {
-#pragma warning disable CS0618 // Type or member is obsolete
- private readonly RazorReferenceManager _referenceManager;
-#pragma warning restore CS0618 // Type or member is obsolete
-
-#pragma warning disable CS0618 // Type or member is obsolete
- public LazyMetadataReferenceFeature(RazorReferenceManager referenceManager)
-#pragma warning restore CS0618 // Type or member is obsolete
- {
- _referenceManager = referenceManager;
- }
-
- ///
- /// Invoking ensures that compilation
- /// references are lazily evaluated.
- ///
- public IReadOnlyList References => _referenceManager.CompilationReferences;
-
- public RazorEngine Engine { get; set; }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Microsoft.AspNetCore.Mvc.Razor.csproj b/src/Microsoft.AspNetCore.Mvc.Razor/Microsoft.AspNetCore.Mvc.Razor.csproj
index 52c7d6814..4296dbb5c 100644
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Microsoft.AspNetCore.Mvc.Razor.csproj
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/Microsoft.AspNetCore.Mvc.Razor.csproj
@@ -13,10 +13,7 @@
-
-
-
@@ -44,7 +41,6 @@
repositoryUrl=$(RepositoryUrl);
repositoryCommit=$(RepositoryCommit);
targetframework=$(TargetFramework);
- MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion=$(MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion);
MicrosoftAspNetCoreRazorRuntimePackageVersion=$(MicrosoftAspNetCoreRazorRuntimePackageVersion);
MicrosoftCodeAnalysisRazorPackageVersion=$(MicrosoftCodeAnalysisRazorPackageVersion);
MicrosoftCodeAnalysisCSharpPackageVersion=$(MicrosoftCodeAnalysisCSharpPackageVersion);
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Microsoft.AspNetCore.Mvc.Razor.nuspec b/src/Microsoft.AspNetCore.Mvc.Razor/Microsoft.AspNetCore.Mvc.Razor.nuspec
index 9ff2439b9..dc898bf15 100644
--- a/src/Microsoft.AspNetCore.Mvc.Razor/Microsoft.AspNetCore.Mvc.Razor.nuspec
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/Microsoft.AspNetCore.Mvc.Razor.nuspec
@@ -16,7 +16,6 @@
-
@@ -25,7 +24,6 @@
-
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/RazorFileHierarchy.cs b/src/Microsoft.AspNetCore.Mvc.Razor/RazorFileHierarchy.cs
new file mode 100644
index 000000000..89f7b43dd
--- /dev/null
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/RazorFileHierarchy.cs
@@ -0,0 +1,44 @@
+// 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.Text;
+
+namespace Microsoft.AspNetCore.Mvc.Razor
+{
+ internal static class RazorFileHierarchy
+ {
+ private const string ViewStartFileName = "_ViewStart.cshtml";
+
+ public static IEnumerable GetViewStartPaths(string path)
+ {
+ if (string.IsNullOrEmpty(path))
+ {
+ throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(path));
+ }
+
+ if (path[0] != '/')
+ {
+ throw new ArgumentException(Resources.RazorProject_PathMustStartWithForwardSlash, nameof(path));
+ }
+
+ if (path.Length == 1)
+ {
+ yield break;
+ }
+
+ var builder = new StringBuilder(path);
+ var maxIterations = 255;
+ var index = path.Length;
+ while (maxIterations-- > 0 && index > 1 && (index = path.LastIndexOf('/', index - 1)) != -1)
+ {
+ builder.Length = index + 1;
+ builder.Append(ViewStartFileName);
+
+ var itemPath = builder.ToString();
+ yield return itemPath;
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngine.cs b/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngine.cs
index 026d8c88a..ad87fbb64 100644
--- a/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngine.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngine.cs
@@ -9,7 +9,6 @@ using System.Linq;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Mvc.ViewEngines;
-using Microsoft.AspNetCore.Razor.Language;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@@ -29,7 +28,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor
public class RazorViewEngine : IRazorViewEngine
{
public static readonly string ViewExtension = ".cshtml";
- private const string ViewStartFileName = "_ViewStart.cshtml";
private const string AreaKey = "area";
private const string ControllerKey = "controller";
@@ -42,19 +40,16 @@ namespace Microsoft.AspNetCore.Mvc.Razor
private readonly HtmlEncoder _htmlEncoder;
private readonly ILogger _logger;
private readonly RazorViewEngineOptions _options;
- private readonly RazorProject _razorFileSystem;
private readonly DiagnosticListener _diagnosticListener;
///
/// Initializes a new instance of the .
///
- [Obsolete("This constructor is obsolete and will be removed in a future version.")]
public RazorViewEngine(
IRazorPageFactoryProvider pageFactory,
IRazorPageActivator pageActivator,
HtmlEncoder htmlEncoder,
IOptions optionsAccessor,
- RazorProject razorProject,
ILoggerFactory loggerFactory,
DiagnosticListener diagnosticListener)
{
@@ -78,28 +73,10 @@ namespace Microsoft.AspNetCore.Mvc.Razor
_pageActivator = pageActivator;
_htmlEncoder = htmlEncoder;
_logger = loggerFactory.CreateLogger();
- _razorFileSystem = razorProject;
_diagnosticListener = diagnosticListener;
ViewLookupCache = new MemoryCache(new MemoryCacheOptions());
}
- ///
- /// Initializes a new instance of the RazorViewEngine
- ///
- public RazorViewEngine(
- IRazorPageFactoryProvider pageFactory,
- IRazorPageActivator pageActivator,
- HtmlEncoder htmlEncoder,
- IOptions optionsAccessor,
- RazorProjectFileSystem razorFileSystem,
- ILoggerFactory loggerFactory,
- DiagnosticListener diagnosticListener)
-#pragma warning disable CS0618 // Type or member is obsolete
- : this (pageFactory, pageActivator, htmlEncoder, optionsAccessor, (RazorProject)razorFileSystem, loggerFactory, diagnosticListener)
-#pragma warning restore CS0618 // Type or member is obsolete
- {
- }
-
///
/// A cache for results of view lookups.
///
@@ -439,10 +416,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor
var viewStartPages = isMainPage ?
GetViewStartPages(viewDescriptor.RelativePath, expirationTokens) :
Array.Empty();
- if (viewDescriptor.IsPrecompiled)
- {
- _logger.PrecompiledViewFound(relativePath);
- }
return new ViewLocationCacheResult(
new ViewLocationCacheItem(factoryResult.RazorPageFactory, relativePath),
@@ -458,9 +431,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor
{
var viewStartPages = new List();
- foreach (var viewStartProjectItem in _razorFileSystem.FindHierarchicalItems(path, ViewStartFileName))
+ foreach (var filePath in RazorFileHierarchy.GetViewStartPaths(path))
{
- var result = _pageFactory.CreateFactory(viewStartProjectItem.FilePath);
+ var result = _pageFactory.CreateFactory(filePath);
var viewDescriptor = result.ViewDescriptor;
if (viewDescriptor?.ExpirationTokens != null)
{
@@ -475,7 +448,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor
// Populate the viewStartPages list so that _ViewStarts appear in the order the need to be
// executed (closest last, furthest first). This is the reverse order in which
// ViewHierarchyUtility.GetViewStartLocations returns _ViewStarts.
- viewStartPages.Insert(0, new ViewLocationCacheItem(result.RazorPageFactory, viewStartProjectItem.FilePath));
+ viewStartPages.Insert(0, new ViewLocationCacheItem(result.RazorPageFactory, filePath));
}
}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngineOptions.cs b/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngineOptions.cs
index 6c6148cb2..d6100bc4e 100644
--- a/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngineOptions.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngineOptions.cs
@@ -1,50 +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;
-using System.Collections;
using System.Collections.Generic;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.Mvc.Infrastructure;
-using Microsoft.AspNetCore.Mvc.Razor.Compilation;
-using Microsoft.CodeAnalysis;
-using Microsoft.Extensions.FileProviders;
namespace Microsoft.AspNetCore.Mvc.Razor
{
///
/// Provides programmatic configuration for the .
///
- public class RazorViewEngineOptions : IEnumerable
+ public class RazorViewEngineOptions
{
- private readonly ICompatibilitySwitch[] _switches;
- private readonly CompatibilitySwitch _allowRecompilingViewsOnFileChange;
- private Action _compilationCallback = c => { };
-
- public RazorViewEngineOptions()
- {
- _allowRecompilingViewsOnFileChange = new CompatibilitySwitch(nameof(AllowRecompilingViewsOnFileChange));
- _switches = new[]
- {
- _allowRecompilingViewsOnFileChange,
- };
- }
-
///
/// Gets a used by the .
///
public IList ViewLocationExpanders { get; } = new List();
- ///
- /// Gets the sequence of instances used by to
- /// locate Razor files.
- ///
- ///
- /// At startup, this is initialized to include an instance of
- /// that is rooted at the application root.
- ///
- public IList FileProviders { get; } = new List();
-
///
/// Gets the locations where will search for views.
///
@@ -165,81 +135,5 @@ namespace Microsoft.AspNetCore.Mvc.Razor
///
///
public IList AreaPageViewLocationFormats { get; } = new List();
-
- ///
- /// Gets the instances that should be included in Razor compilation, along with
- /// those discovered by s.
- ///
- [Obsolete("This property is obsolete and will be removed in a future version. See https://aka.ms/AA1x4gg for details.")]
- public IList AdditionalCompilationReferences { get; } = new List();
-
- ///
- /// Gets or sets the callback that is used to customize Razor compilation
- /// to change compilation settings you can update property.
- ///
- ///
- /// Customizations made here would not reflect in tooling (Intellisense).
- ///
- [Obsolete("This property is obsolete and will be removed in a future version. See https://aka.ms/AA1x4gg for details.")]
- public Action CompilationCallback
- {
- get => _compilationCallback;
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- _compilationCallback = value;
- }
- }
-
- ///
- /// Gets or sets a value that determines if Razor files (Razor Views and Razor Pages) are recompiled and updated
- /// if files change on disk.
- ///
- /// When , MVC will use to watch for changes to
- /// Razor files in configured instances.
- ///
- ///
- ///
- /// The default value is if the version is
- /// or earlier. If the version is later and is Development,
- /// the default value is . Otherwise, the default value is .
- ///
- ///
- ///
- /// This property is associated with a compatibility switch and can provide a different behavior depending on
- /// the configured compatibility version for the application. See for
- /// guidance and examples of setting the application's compatibility version.
- ///
- ///
- /// Configuring the desired value of the compatibility switch by calling this property's setter will take
- /// precedence over the value implied by the application's .
- ///
- ///
- /// If the application's compatibility version is set to or
- /// lower then this setting will have the value unless explicitly configured.
- ///
- ///
- /// If the application's compatibility version is set to or
- /// higher then this setting will have the value unless
- /// is Development or the value is explicitly configured.
- ///
- ///
- public bool AllowRecompilingViewsOnFileChange
- {
- // Note: When compatibility switches are removed in 3.0, this property should be retained as a regular boolean property.
- get => _allowRecompilingViewsOnFileChange.Value;
- set => _allowRecompilingViewsOnFileChange.Value = value;
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return ((IEnumerable)_switches).GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator() => _switches.GetEnumerator();
}
}
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngineOptionsSetup.cs b/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngineOptionsSetup.cs
index 6747d8772..d6ffc66da 100644
--- a/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngineOptionsSetup.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngineOptionsSetup.cs
@@ -2,45 +2,20 @@
// 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 Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.Mvc.Infrastructure;
-using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Mvc.Razor
{
- internal class RazorViewEngineOptionsSetup :
- ConfigureCompatibilityOptions,
- IConfigureOptions
+ internal class RazorViewEngineOptionsSetup : IConfigureOptions
{
private readonly IHostingEnvironment _hostingEnvironment;
- public RazorViewEngineOptionsSetup(
- IHostingEnvironment hostingEnvironment,
- ILoggerFactory loggerFactory,
- IOptions compatibilityOptions)
- : base(loggerFactory, compatibilityOptions)
+ public RazorViewEngineOptionsSetup(IHostingEnvironment hostingEnvironment)
{
_hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
}
- protected override IReadOnlyDictionary DefaultValues
- {
- get
- {
- var values = new Dictionary();
- if (Version < CompatibilityVersion.Version_2_2)
- {
- // Default to true in 2.1 or earlier. In 2.2, we have to conditionally enable this
- // and consequently this switch has no default value.
- values[nameof(RazorViewEngineOptions.AllowRecompilingViewsOnFileChange)] = true;
- }
-
- return values;
- }
- }
-
public void Configure(RazorViewEngineOptions options)
{
if (options == null)
@@ -48,22 +23,12 @@ namespace Microsoft.AspNetCore.Mvc.Razor
throw new ArgumentNullException(nameof(options));
}
- if (_hostingEnvironment.ContentRootFileProvider != null)
- {
- options.FileProviders.Add(_hostingEnvironment.ContentRootFileProvider);
- }
-
options.ViewLocationFormats.Add("/Views/{1}/{0}" + RazorViewEngine.ViewExtension);
options.ViewLocationFormats.Add("/Views/Shared/{0}" + RazorViewEngine.ViewExtension);
options.AreaViewLocationFormats.Add("/Areas/{2}/Views/{1}/{0}" + RazorViewEngine.ViewExtension);
options.AreaViewLocationFormats.Add("/Areas/{2}/Views/Shared/{0}" + RazorViewEngine.ViewExtension);
options.AreaViewLocationFormats.Add("/Views/Shared/{0}" + RazorViewEngine.ViewExtension);
-
- if (_hostingEnvironment.IsDevelopment())
- {
- options.AllowRecompilingViewsOnFileChange = true;
- }
}
}
}
\ No newline at end of file
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/breakingchanges.netcore.json b/src/Microsoft.AspNetCore.Mvc.Razor/breakingchanges.netcore.json
index ee5093114..c23845969 100644
--- a/src/Microsoft.AspNetCore.Mvc.Razor/breakingchanges.netcore.json
+++ b/src/Microsoft.AspNetCore.Mvc.Razor/breakingchanges.netcore.json
@@ -1,4 +1,24 @@
[
+ {
+ "TypeId": "public abstract class Microsoft.AspNetCore.Mvc.Razor.Compilation.RazorReferenceManager",
+ "Kind": "Removal"
+ },
+ {
+ "TypeId": "public class Microsoft.AspNetCore.Mvc.Razor.Compilation.CompilationFailedException : System.Exception, Microsoft.AspNetCore.Diagnostics.ICompilationException",
+ "Kind": "Removal"
+ },
+ {
+ "TypeId": "public class Microsoft.AspNetCore.Mvc.Razor.Compilation.MetadataReferenceFeature",
+ "Kind": "Removal"
+ },
+ {
+ "TypeId": "public class Microsoft.AspNetCore.Mvc.Razor.Compilation.MetadataReferenceFeatureProvider : Microsoft.AspNetCore.Mvc.ApplicationParts.IApplicationFeatureProvider",
+ "Kind": "Removal"
+ },
+ {
+ "TypeId": "public class Microsoft.AspNetCore.Mvc.Razor.Compilation.RoslynCompilationContext",
+ "Kind": "Removal"
+ },
{
"TypeId": "public class Microsoft.AspNetCore.Mvc.Razor.RazorViewEngine : Microsoft.AspNetCore.Mvc.Razor.IRazorViewEngine",
"MemberId": "public .ctor(Microsoft.AspNetCore.Mvc.Razor.IRazorPageFactoryProvider pageFactory, Microsoft.AspNetCore.Mvc.Razor.IRazorPageActivator pageActivator, System.Text.Encodings.Web.HtmlEncoder htmlEncoder, Microsoft.Extensions.Options.IOptions optionsAccessor, Microsoft.AspNetCore.Razor.Language.RazorProject razorProject, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, System.Diagnostics.DiagnosticSource diagnosticSource)",
@@ -13,5 +33,35 @@
"TypeId": "public class Microsoft.AspNetCore.Mvc.Razor.RazorView : Microsoft.AspNetCore.Mvc.ViewEngines.IView",
"MemberId": "public .ctor(Microsoft.AspNetCore.Mvc.Razor.IRazorViewEngine viewEngine, Microsoft.AspNetCore.Mvc.Razor.IRazorPageActivator pageActivator, System.Collections.Generic.IReadOnlyList viewStartPages, Microsoft.AspNetCore.Mvc.Razor.IRazorPage razorPage, System.Text.Encodings.Web.HtmlEncoder htmlEncoder, System.Diagnostics.DiagnosticSource diagnosticSource)",
"Kind": "Removal"
+ },
+ {
+ "TypeId": "public class Microsoft.AspNetCore.Mvc.Razor.RazorViewEngineOptions",
+ "MemberId": "public System.Action get_CompilationCallback()",
+ "Kind": "Removal"
+ },
+ {
+ "TypeId": "public class Microsoft.AspNetCore.Mvc.Razor.RazorViewEngineOptions",
+ "MemberId": "public System.Collections.Generic.IList get_AdditionalCompilationReferences()",
+ "Kind": "Removal"
+ },
+ {
+ "TypeId": "public class Microsoft.AspNetCore.Mvc.Razor.RazorViewEngineOptions",
+ "MemberId": "public System.Void set_CompilationCallback(System.Action value)",
+ "Kind": "Removal"
+ },
+ {
+ "TypeId": "public class Microsoft.AspNetCore.Mvc.Razor.RazorViewEngineOptions",
+ "MemberId": "public System.Collections.Generic.IList get_FileProviders()",
+ "Kind": "Removal"
+ },
+ {
+ "TypeId": "public class Microsoft.AspNetCore.Mvc.Razor.Compilation.CompiledViewDescriptor",
+ "MemberId": "public System.Boolean get_IsPrecompiled()",
+ "Kind": "Removal"
+ },
+ {
+ "TypeId": "public class Microsoft.AspNetCore.Mvc.Razor.Compilation.CompiledViewDescriptor",
+ "MemberId": "public System.Void set_IsPrecompiled(System.Boolean value)",
+ "Kind": "Removal"
}
-]
+]
\ No newline at end of file
diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/CompiledPageRouteModelProvider.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/CompiledPageRouteModelProvider.cs
index 9660bffa2..7471af285 100644
--- a/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/CompiledPageRouteModelProvider.cs
+++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/CompiledPageRouteModelProvider.cs
@@ -6,11 +6,9 @@ using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
-using Microsoft.AspNetCore.Mvc.Razor.Extensions;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
using Microsoft.AspNetCore.Razor.Hosting;
-using Microsoft.AspNetCore.Razor.Language;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@@ -18,23 +16,20 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
{
internal class CompiledPageRouteModelProvider : IPageRouteModelProvider
{
+ private static readonly string RazorPageDocumentKind = "mvc.1.0.razor-page";
+ private static readonly string RouteTemplateKey = "RouteTemplate";
private readonly ApplicationPartManager _applicationManager;
private readonly RazorPagesOptions _pagesOptions;
- private readonly RazorProjectEngine _razorProjectEngine;
- private readonly ILogger _logger;
private readonly PageRouteModelFactory _routeModelFactory;
public CompiledPageRouteModelProvider(
ApplicationPartManager applicationManager,
IOptions pagesOptionsAccessor,
- RazorProjectEngine razorProjectEngine,
ILogger logger)
{
_applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
_pagesOptions = pagesOptionsAccessor?.Value ?? throw new ArgumentNullException(nameof(pagesOptionsAccessor));
- _razorProjectEngine = razorProjectEngine ?? throw new ArgumentNullException(nameof(razorProjectEngine));
- _logger = logger ?? throw new ArgumentNullException(nameof(razorProjectEngine));
- _routeModelFactory = new PageRouteModelFactory(_pagesOptions, _logger);
+ _routeModelFactory = new PageRouteModelFactory(_pagesOptions, logger);
}
public int Order => -1000;
@@ -75,11 +70,6 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
continue;
}
- if (!viewDescriptor.IsPrecompiled)
- {
- continue;
- }
-
if (IsRazorPage(viewDescriptor))
{
yield return viewDescriptor;
@@ -90,7 +80,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
{
if (viewDescriptor.Item != null)
{
- return viewDescriptor.Item.Kind == RazorPageDocumentClassifierPass.RazorPageDocumentKind;
+ return viewDescriptor.Item.Kind == RazorPageDocumentKind;
}
else if (viewDescriptor.ViewAttribute != null)
{
@@ -119,12 +109,6 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
var areaRootDirectory = "/Areas/";
foreach (var viewDescriptor in GetViewDescriptors(_applicationManager))
{
- if (viewDescriptor.Item != null && !ChecksumValidator.IsItemValid(_razorProjectEngine.FileSystem, viewDescriptor.Item))
- {
- // If we get here, this compiled Page has different local content, so ignore it.
- continue;
- }
-
var relativePath = viewDescriptor.RelativePath;
var routeTemplate = GetRouteTemplate(viewDescriptor);
PageRouteModel routeModel = null;
@@ -158,7 +142,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
{
return viewDescriptor.Item.Metadata
.OfType()
- .FirstOrDefault(f => f.Key == RazorPageDocumentClassifierPass.RouteTemplateKey)
+ .FirstOrDefault(f => f.Key == RouteTemplateKey)
?.Value;
}
diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/RazorProjectPageRouteModelProvider.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/RazorProjectPageRouteModelProvider.cs
deleted file mode 100644
index 4f2dcc65c..000000000
--- a/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/RazorProjectPageRouteModelProvider.cs
+++ /dev/null
@@ -1,119 +0,0 @@
-// 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.Linq;
-using Microsoft.AspNetCore.Mvc.RazorPages;
-using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
-using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
-
-namespace Microsoft.AspNetCore.Mvc.ApplicationModels
-{
- internal class RazorProjectPageRouteModelProvider : IPageRouteModelProvider
- {
- private const string AreaRootDirectory = "/Areas";
- private readonly RazorProjectFileSystem _razorFileSystem;
- private readonly RazorPagesOptions _pagesOptions;
- private readonly PageRouteModelFactory _routeModelFactory;
- private readonly ILogger _logger;
-
- public RazorProjectPageRouteModelProvider(
- RazorProjectFileSystem razorFileSystem,
- IOptions pagesOptionsAccessor,
- ILoggerFactory loggerFactory)
- {
- _razorFileSystem = razorFileSystem;
- _pagesOptions = pagesOptionsAccessor.Value;
- _logger = loggerFactory.CreateLogger();
- _routeModelFactory = new PageRouteModelFactory(_pagesOptions, _logger);
- }
-
- ///
- /// Ordered to execute after .
- ///
- public int Order => -1000 + 10;
-
- public void OnProvidersExecuted(PageRouteModelProviderContext context)
- {
- }
-
- public void OnProvidersExecuting(PageRouteModelProviderContext context)
- {
- // When RootDirectory and AreaRootDirectory overlap, e.g. RootDirectory = /, AreaRootDirectory = /Areas;
- // we need to ensure that the page is only route-able via the area route. By adding area routes first,
- // we'll ensure non area routes get skipped when it encounters an IsAlreadyRegistered check.
-
- if (_pagesOptions.AllowAreas)
- {
- AddAreaPageModels(context);
- }
-
- AddPageModels(context);
- }
-
- private void AddPageModels(PageRouteModelProviderContext context)
- {
- foreach (var item in _razorFileSystem.EnumerateItems(_pagesOptions.RootDirectory))
- {
- var relativePath = item.CombinedPath;
- if (context.RouteModels.Any(m => string.Equals(relativePath, m.RelativePath, StringComparison.OrdinalIgnoreCase)))
- {
- // A route for this file was already registered either by the CompiledPageRouteModel or as an area route.
- // by this provider. Skip registering an additional entry.
-
- // Note: We're comparing duplicates based on root-relative paths. This eliminates a page from being discovered
- // by overlapping area and non-area routes where ViewEnginePath would be different.
- continue;
- }
-
- if (!PageDirectiveFeature.TryGetPageDirective(_logger, item, out var routeTemplate))
- {
- // .cshtml pages without @page are not RazorPages.
- continue;
- }
-
- if (_pagesOptions.AllowAreas && relativePath.StartsWith(AreaRootDirectory, StringComparison.OrdinalIgnoreCase))
- {
- // Ignore Razor pages that are under the area root directory when AllowAreas is enabled.
- // Conforming page paths will be added by AddAreaPageModels.
- _logger.UnsupportedAreaPath(relativePath);
- continue;
- }
-
- var routeModel = _routeModelFactory.CreateRouteModel(relativePath, routeTemplate);
- if (routeModel != null)
- {
- context.RouteModels.Add(routeModel);
- }
- }
- }
-
- private void AddAreaPageModels(PageRouteModelProviderContext context)
- {
- foreach (var item in _razorFileSystem.EnumerateItems(AreaRootDirectory))
- {
- var relativePath = item.CombinedPath;
- if (context.RouteModels.Any(m => string.Equals(relativePath, m.RelativePath, StringComparison.OrdinalIgnoreCase)))
- {
- // A route for this file was already registered either by the CompiledPageRouteModel.
- // Skip registering an additional entry.
- continue;
- }
-
- if (!PageDirectiveFeature.TryGetPageDirective(_logger, item, out var routeTemplate))
- {
- // .cshtml pages without @page are not RazorPages.
- continue;
- }
-
- var routeModel = _routeModelFactory.CreateAreaRouteModel(relativePath, routeTemplate);
- if (routeModel != null)
- {
- context.RouteModels.Add(routeModel);
- }
- }
- }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/DependencyInjection/MvcRazorPagesMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/DependencyInjection/MvcRazorPagesMvcCoreBuilderExtensions.cs
index 18a88f803..4de29ac56 100644
--- a/src/Microsoft.AspNetCore.Mvc.RazorPages/DependencyInjection/MvcRazorPagesMvcCoreBuilderExtensions.cs
+++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/DependencyInjection/MvcRazorPagesMvcCoreBuilderExtensions.cs
@@ -88,9 +88,6 @@ namespace Microsoft.Extensions.DependencyInjection
// Action description and invocation
services.TryAddEnumerable(
ServiceDescriptor.Singleton());
- services.TryAddSingleton();
- services.TryAddEnumerable(
- ServiceDescriptor.Singleton());
services.TryAddEnumerable(
ServiceDescriptor.Singleton());
diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageActionDescriptorChangeProvider.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageActionDescriptorChangeProvider.cs
deleted file mode 100644
index 8ede4ccf1..000000000
--- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageActionDescriptorChangeProvider.cs
+++ /dev/null
@@ -1,116 +0,0 @@
-// 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.Diagnostics;
-using System.Linq;
-using Microsoft.AspNetCore.Mvc.Infrastructure;
-using Microsoft.AspNetCore.Mvc.Razor;
-using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.Extensions.FileProviders;
-using Microsoft.Extensions.Options;
-using Microsoft.Extensions.Primitives;
-
-namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
-{
- internal class PageActionDescriptorChangeProvider : IActionDescriptorChangeProvider
- {
- private readonly IFileProvider _fileProvider;
- private readonly string[] _searchPatterns;
- private readonly string[] _additionalFilesToTrack;
- private readonly bool _watchForChanges;
-
- public PageActionDescriptorChangeProvider(
- RazorTemplateEngine templateEngine,
- IRazorViewEngineFileProviderAccessor fileProviderAccessor,
- IOptions razorPagesOptions,
- IOptions razorViewEngineOptions)
- {
- if (templateEngine == null)
- {
- throw new ArgumentNullException(nameof(templateEngine));
- }
-
- if (fileProviderAccessor == null)
- {
- throw new ArgumentNullException(nameof(fileProviderAccessor));
- }
-
- if (razorPagesOptions == null)
- {
- throw new ArgumentNullException(nameof(razorPagesOptions));
- }
-
- _watchForChanges = razorViewEngineOptions.Value.AllowRecompilingViewsOnFileChange;
- if (!_watchForChanges)
- {
- // No need to do any additional work if we aren't going to be watching for file changes.
- return;
- }
-
- _fileProvider = fileProviderAccessor.FileProvider;
-
- var rootDirectory = razorPagesOptions.Value.RootDirectory;
- Debug.Assert(!string.IsNullOrEmpty(rootDirectory));
- rootDirectory = rootDirectory.TrimEnd('/');
-
- // Search pattern that matches all cshtml files under the Pages RootDirectory
- var pagesRootSearchPattern = rootDirectory + "/**/*.cshtml";
-
- // pagesRootSearchPattern will miss _ViewImports outside the RootDirectory despite these influencing
- // compilation. e.g. when RootDirectory = /Dir1/Dir2, the search pattern will ignore changes to
- // [/_ViewImports.cshtml, /Dir1/_ViewImports.cshtml]. We need to additionally account for these.
- var importFileAtPagesRoot = rootDirectory + "/" + templateEngine.Options.ImportsFileName;
- var additionalImportFilePaths = templateEngine.GetImportItems(importFileAtPagesRoot)
- .Select(item => item.FilePath);
-
- if (razorPagesOptions.Value.AllowAreas)
- {
- // Search pattern that matches all cshtml files under the Pages AreaRootDirectory
- var areaRootSearchPattern = "/Areas/**/*.cshtml";
-
- var importFileAtAreaPagesRoot = $"/Areas/{templateEngine.Options.ImportsFileName}";
- var importPathsOutsideAreaPagesRoot = templateEngine.GetImportItems(importFileAtAreaPagesRoot)
- .Select(item => item.FilePath);
-
- additionalImportFilePaths = additionalImportFilePaths
- .Concat(importPathsOutsideAreaPagesRoot)
- .Distinct(StringComparer.OrdinalIgnoreCase);
-
- _searchPatterns = new[]
- {
- pagesRootSearchPattern,
- areaRootSearchPattern
- };
- }
- else
- {
- _searchPatterns = new[] { pagesRootSearchPattern, };
- }
-
- _additionalFilesToTrack = additionalImportFilePaths.ToArray();
- }
-
- public IChangeToken GetChangeToken()
- {
- if (!_watchForChanges)
- {
- return NullChangeToken.Singleton;
- }
-
- var changeTokens = new IChangeToken[_additionalFilesToTrack.Length + _searchPatterns.Length];
- for (var i = 0; i < _additionalFilesToTrack.Length; i++)
- {
- changeTokens[i] = _fileProvider.Watch(_additionalFilesToTrack[i]);
- }
-
- for (var i = 0; i < _searchPatterns.Length; i++)
- {
- var wildcardChangeToken = _fileProvider.Watch(_searchPatterns[i]);
- changeTokens[_additionalFilesToTrack.Length + i] = wildcardChangeToken;
- }
-
- return new CompositeChangeToken(changeTokens);
- }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageActionInvokerProvider.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageActionInvokerProvider.cs
index e5fd4e97c..ffb9f9330 100644
--- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageActionInvokerProvider.cs
+++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageActionInvokerProvider.cs
@@ -12,7 +12,6 @@ using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
-using Microsoft.AspNetCore.Razor.Language;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@@ -36,7 +35,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
private readonly MvcOptions _mvcOptions;
private readonly HtmlHelperOptions _htmlHelperOptions;
private readonly IPageHandlerMethodSelector _selector;
- private readonly RazorProjectFileSystem _razorFileSystem;
private readonly DiagnosticListener _diagnosticListener;
private readonly ILogger _logger;
private readonly IActionResultTypeMapper _mapper;
@@ -56,7 +54,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
IOptions mvcOptions,
IOptions htmlHelperOptions,
IPageHandlerMethodSelector selector,
- RazorProjectFileSystem razorFileSystem,
DiagnosticListener diagnosticListener,
ILoggerFactory loggerFactory,
IActionResultTypeMapper mapper)
@@ -75,7 +72,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
_mvcOptions = mvcOptions.Value;
_htmlHelperOptions = htmlHelperOptions.Value;
_selector = selector;
- _razorFileSystem = razorFileSystem;
_diagnosticListener = diagnosticListener;
_logger = loggerFactory.CreateLogger();
_mapper = mapper;
@@ -215,12 +211,9 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
{
var viewStartFactories = new List>();
// Always pick up all _ViewStarts, including the ones outside the Pages root.
- var viewStartItems = _razorFileSystem.FindHierarchicalItems(
- descriptor.RelativePath,
- ViewStartFileName);
- foreach (var item in viewStartItems)
+ foreach (var filePath in RazorFileHierarchy.GetViewStartPaths(descriptor.RelativePath))
{
- var factoryResult = _razorPageFactoryProvider.CreateFactory(item.FilePath);
+ var factoryResult = _razorPageFactoryProvider.CreateFactory(filePath);
if (factoryResult.Success)
{
viewStartFactories.Insert(0, factoryResult.RazorPageFactory);
diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageDirectiveFeature.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageDirectiveFeature.cs
deleted file mode 100644
index db310a80a..000000000
--- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageDirectiveFeature.cs
+++ /dev/null
@@ -1,110 +0,0 @@
-// 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 Microsoft.AspNetCore.Mvc.Razor.Extensions;
-using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.AspNetCore.Razor.Language.Intermediate;
-using Microsoft.Extensions.Logging;
-
-namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
-{
- public static class PageDirectiveFeature
- {
- private static readonly RazorProjectEngine PageDirectiveEngine = RazorProjectEngine.Create(RazorConfiguration.Default, new EmptyRazorProjectFileSystem(), builder =>
- {
- for (var i = builder.Phases.Count - 1; i >= 0; i--)
- {
- var phase = builder.Phases[i];
- builder.Phases.RemoveAt(i);
- if (phase is IRazorDocumentClassifierPhase)
- {
- break;
- }
- }
-
- RazorExtensions.Register(builder);
- builder.Features.Add(new PageDirectiveParserOptionsFeature());
- });
-
- public static bool TryGetPageDirective(ILogger logger, RazorProjectItem projectItem, out string template)
- {
- if (projectItem == null)
- {
- throw new ArgumentNullException(nameof(projectItem));
- }
-
- var codeDocument = PageDirectiveEngine.Process(projectItem);
-
- var documentIRNode = codeDocument.GetDocumentIntermediateNode();
- if (PageDirective.TryGetPageDirective(documentIRNode, out var pageDirective))
- {
- if (pageDirective.DirectiveNode is MalformedDirectiveIntermediateNode malformedNode)
- {
- logger.MalformedPageDirective(projectItem.FilePath, malformedNode.Diagnostics);
- }
-
- template = pageDirective.RouteTemplate;
- return true;
- }
-
- template = null;
- return false;
- }
-
- private class PageDirectiveParserOptionsFeature : RazorEngineFeatureBase, IConfigureRazorParserOptionsFeature
- {
- public int Order { get; }
-
- public void Configure(RazorParserOptionsBuilder options)
- {
- options.ParseLeadingDirectives = true;
- }
- }
-
- private class EmptyRazorProjectFileSystem : RazorProjectFileSystem
- {
- public override IEnumerable EnumerateItems(string basePath)
- {
- return Enumerable.Empty();
- }
-
- public override IEnumerable FindHierarchicalItems(string basePath, string path, string fileName)
- {
- return Enumerable.Empty();
- }
-
- public override RazorProjectItem GetItem(string path)
- {
- return new NotFoundProjectItem(string.Empty, path);
- }
-
- private class NotFoundProjectItem : RazorProjectItem
- {
- public NotFoundProjectItem(string basePath, string path)
- {
- BasePath = basePath;
- FilePath = path;
- }
-
- ///
- public override string BasePath { get; }
-
- ///
- public override string FilePath { get; }
-
- ///
- public override bool Exists => false;
-
- ///
- public override string PhysicalPath => throw new NotSupportedException();
-
- ///
- public override Stream Read() => throw new NotSupportedException();
- }
- }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/PageLoggerExtensions.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/PageLoggerExtensions.cs
index 7d1464263..2407767fc 100644
--- a/src/Microsoft.AspNetCore.Mvc.RazorPages/PageLoggerExtensions.cs
+++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/PageLoggerExtensions.cs
@@ -2,11 +2,9 @@
// 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 Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
-using Microsoft.AspNetCore.Razor.Language;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Mvc.RazorPages
@@ -151,20 +149,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
_pageFilterShortCircuit(logger, filter, null);
}
- public static void MalformedPageDirective(this ILogger logger, string filePath, IList diagnostics)
- {
- if (logger.IsEnabled(LogLevel.Warning))
- {
- var messages = new string[diagnostics.Count];
- for (var i = 0; i < diagnostics.Count; i++)
- {
- messages[i] = diagnostics[i].GetMessage();
- }
-
- _malformedPageDirective(logger, filePath, messages, null);
- }
- }
-
public static void NotMostEffectiveFilter(this ILogger logger, Type policyType)
{
_notMostEffectiveFilter(logger, policyType, null);
diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/breakingchanges.netcore.json b/src/Microsoft.AspNetCore.Mvc.RazorPages/breakingchanges.netcore.json
index 9bb751718..e2fa5d1d6 100644
--- a/src/Microsoft.AspNetCore.Mvc.RazorPages/breakingchanges.netcore.json
+++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/breakingchanges.netcore.json
@@ -23,5 +23,9 @@
"TypeId": "public class Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageResultExecutor : Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor",
"MemberId": "public .ctor(Microsoft.AspNetCore.Mvc.Infrastructure.IHttpResponseStreamWriterFactory writerFactory, Microsoft.AspNetCore.Mvc.ViewEngines.ICompositeViewEngine compositeViewEngine, Microsoft.AspNetCore.Mvc.Razor.IRazorViewEngine razorViewEngine, Microsoft.AspNetCore.Mvc.Razor.IRazorPageActivator razorPageActivator, System.Diagnostics.DiagnosticSource diagnosticSource, System.Text.Encodings.Web.HtmlEncoder htmlEncoder)",
"Kind": "Removal"
+ },
+ {
+ "TypeId": "public static class Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageDirectiveFeature",
+ "Kind": "Removal"
}
]
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ErrorPageTests.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ErrorPageTests.cs
index 7241fbf2e..985b07e0e 100644
--- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ErrorPageTests.cs
+++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ErrorPageTests.cs
@@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
public HttpClient Client { get; }
- [Fact]
+ [Fact(Skip = "https://github.com/aspnet/Mvc/issues/8753")]
public async Task CompilationFailuresAreListedByErrorPageMiddleware()
{
// Arrange
@@ -45,7 +45,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
Assert.DoesNotContain(PreserveCompilationContextMessage, content);
}
- [Fact]
+ [Fact(Skip = "https://github.com/aspnet/Mvc/issues/8753")]
public async Task ParseFailuresAreListedByErrorPageMiddleware()
{
// Arrange
@@ -67,7 +67,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
Assert.Contains(expected, content);
}
- [Fact]
+ [Fact(Skip = "https://github.com/aspnet/Mvc/issues/8753")]
public async Task CompilationFailuresFromViewImportsAreListed()
{
// Arrange
@@ -90,7 +90,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
Assert.Contains(expectedCompilationContent, content);
}
- [Fact]
+ [Fact(Skip = "https://github.com/aspnet/Mvc/issues/8753")]
public async Task RuntimeErrorAreListedByErrorPageMiddleware()
{
// Arrange
diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorBuildTest.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorBuildTest.cs
index 187e9d9ab..08097d522 100644
--- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorBuildTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorBuildTest.cs
@@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
Assert.Equal("Hello from buildtime-compiled precompilation view!", responseBody.Trim());
}
- [Fact]
+ [Fact(Skip = "https://github.com/aspnet/Mvc/issues/8753")]
public async Task Rzc_LocalPageWithDifferentContent_IsUsed()
{
// Act
@@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
Assert.Equal("Hello from runtime-compiled rzc page!", responseBody.Trim());
}
- [Fact]
+ [Fact(Skip = "https://github.com/aspnet/Mvc/issues/8753")]
public async Task Rzc_LocalViewWithDifferentContent_IsUsed()
{
// Act
diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorFileUpdateTests.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorFileUpdateTests.cs
deleted file mode 100644
index b4aee9ad9..000000000
--- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorFileUpdateTests.cs
+++ /dev/null
@@ -1,131 +0,0 @@
-// 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.Net.Http;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.Mvc.Razor;
-using Microsoft.AspNetCore.TestHost;
-using Microsoft.Extensions.DependencyInjection;
-using Xunit;
-
-namespace Microsoft.AspNetCore.Mvc.FunctionalTests
-{
- // Verifies that updating Razor files (views and pages) with AllowRecompilingViewsOnFileChange=true works
- public class RazorFileUpdateTests : IClassFixture>
- {
- public RazorFileUpdateTests(MvcTestFixture fixture)
- {
- var factory = fixture.WithWebHostBuilder(builder =>
- {
- builder.UseStartup();
- builder.ConfigureTestServices(services =>
- {
- services.Configure(options => options.AllowRecompilingViewsOnFileChange = true);
- });
- });
- Client = factory.CreateDefaultClient();
- }
-
- public HttpClient Client { get; }
-
- [Fact]
- public async Task RazorViews_AreUpdatedOnChange()
- {
- // Arrange
- var expected1 = "Original content";
- var expected2 = "New content";
- var path = "/Views/UpdateableShared/_Partial.cshtml";
-
- // Act - 1
- var body = await Client.GetStringAsync("/UpdateableFileProvider");
-
- // Assert - 1
- Assert.Equal(expected1, body.Trim(), ignoreLineEndingDifferences: true);
-
- // Act - 2
- await UpdateFile(path, expected2);
- body = await Client.GetStringAsync("/UpdateableFileProvider");
-
- // Assert - 2
- Assert.Equal(expected2, body.Trim(), ignoreLineEndingDifferences: true);
- }
-
- [Fact]
- public async Task RazorViews_AreUpdatedWhenViewImportsChange()
- {
- // Arrange
- var content = "@GetType().Assembly.FullName";
- await UpdateFile("/Views/UpdateableIndex/Index.cshtml", content);
- var initial = await Client.GetStringAsync("/UpdateableFileProvider");
-
- // Act
- // Trigger a change in ViewImports
- await UpdateFile("/Views/UpdateableIndex/_ViewImports.cshtml", string.Empty);
- var updated = await Client.GetStringAsync("/UpdateableFileProvider");
-
- // Assert
- Assert.NotEqual(initial, updated);
- }
-
- [Fact]
- public async Task RazorPages_AreUpdatedOnChange()
- {
- // Arrange
- var expected1 = "Original content";
- var expected2 = "New content";
-
- // Act - 1
- var body = await Client.GetStringAsync("/UpdateablePage");
-
- // Assert - 1
- Assert.Equal(expected1, body.Trim(), ignoreLineEndingDifferences: true);
-
- // Act - 2
- await UpdateRazorPages();
- await UpdateFile("/Pages/UpdateablePage.cshtml", "@page" + Environment.NewLine + expected2);
- body = await Client.GetStringAsync("/UpdateablePage");
-
- // Assert - 2
- Assert.Equal(expected2, body.Trim(), ignoreLineEndingDifferences: true);
- }
-
- [Fact]
- public async Task RazorPages_AreUpdatedWhenViewImportsChange()
- {
- // Arrange
- var content = "@GetType().Assembly.FullName";
- await UpdateFile("/Pages/UpdateablePage.cshtml", "@page" + Environment.NewLine + content);
- var initial = await Client.GetStringAsync("/UpdateablePage");
-
- // Act
- // Trigger a change in ViewImports
- await UpdateRazorPages();
- await UpdateFile("/Pages/UpdateablePage.cshtml", "@page" + Environment.NewLine + content);
- var updated = await Client.GetStringAsync("/UpdateablePage");
-
- // Assert
- Assert.NotEqual(initial, updated);
- }
-
- private async Task UpdateFile(string path, string content)
- {
- var updateContent = new FormUrlEncodedContent(new Dictionary
- {
- { "path", path },
- { "content", content },
- });
-
- var response = await Client.PostAsync($"/UpdateableFileProvider/Update", updateContent);
- response.EnsureSuccessStatusCode();
- }
-
- private async Task UpdateRazorPages()
- {
- var response = await Client.PostAsync($"/UpdateableFileProvider/UpdateRazorPages", new StringContent(string.Empty));
- response.EnsureSuccessStatusCode();
- }
- }
-}
diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ViewEngineTests.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ViewEngineTests.cs
index 7c23e4c37..84283fe77 100644
--- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ViewEngineTests.cs
+++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ViewEngineTests.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
+using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Threading.Tasks;
@@ -66,9 +67,12 @@ ViewWithNestedLayout-Content
public async Task RazorView_ExecutesPageAndLayout(string actionName, string expected)
{
// Arrange & Act
- var body = await Client.GetStringAsync("http://localhost/ViewEngine/" + actionName);
+ var response = await Client.GetAsync("http://localhost/ViewEngine/" + actionName);
// Assert
+ await response.AssertStatusCodeAsync(HttpStatusCode.OK);
+ var body = await response.Content.ReadAsStringAsync();
+
Assert.Equal(expected, body.Trim(), ignoreLineEndingDifferences: true);
}
@@ -240,17 +244,19 @@ ViewWithNestedLayout-Content
public async Task RazorViewEngine_RendersPartialViews(string actionName, string expected)
{
// Arrange & Act
- var body = await Client.GetStringAsync("http://localhost/PartialViewEngine/" + actionName);
+ var response = await Client.GetAsync("http://localhost/PartialViewEngine/" + actionName);
// Assert
+ await response.AssertStatusCodeAsync(HttpStatusCode.OK);
+ var body = await response.Content.ReadAsStringAsync();
Assert.Equal(expected, body.Trim(), ignoreLineEndingDifferences: true);
}
- [Fact]
+ [Fact(Skip = "https://github.com/aspnet/Mvc/issues/8754")]
public Task RazorViewEngine_RendersViewsFromEmbeddedFileProvider_WhenLookedupByName()
=> RazorViewEngine_RendersIndexViewsFromEmbeddedFileProvider("/EmbeddedViews/LookupByName");
- [Fact]
+ [Fact(Skip = "https://github.com/aspnet/Mvc/issues/8754")]
public Task RazorViewEngine_RendersViewsFromEmbeddedFileProvider_WhenLookedupByPath()
=> RazorViewEngine_RendersIndexViewsFromEmbeddedFileProvider("/EmbeddedViews/LookupByPath");
@@ -479,7 +485,7 @@ Partial";
Assert.Equal(expected, responseContent, ignoreLineEndingDifferences: true);
}
- [Fact]
+ [Fact(Skip = "https://github.com/aspnet/Mvc/issues/8754")]
public async Task ViewEngine_ResolvesPathsWithSlashesThatDoNotHaveExtensions()
{
// Arrange
diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/CSharpCompilerTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/CSharpCompilerTest.cs
deleted file mode 100644
index f25d1fc02..000000000
--- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/CSharpCompilerTest.cs
+++ /dev/null
@@ -1,408 +0,0 @@
-// 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.Linq;
-using System.Reflection;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.Emit;
-using Microsoft.CodeAnalysis.Text;
-using Moq;
-using Xunit;
-using DependencyContextCompilationOptions = Microsoft.Extensions.DependencyModel.CompilationOptions;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
-{
- public class CSharpCompilerTest
- {
-#pragma warning disable CS0618 // Type or member is obsolete
- private readonly RazorReferenceManager ReferenceManager = Mock.Of();
-#pragma warning restore CS0618 // Type or member is obsolete
-
- [Theory]
- [InlineData(null)]
- [InlineData("")]
- public void GetCompilationOptions_ReturnsDefaultOptionsIfApplicationNameIsNullOrEmpty(string name)
- {
- // Arrange
- var hostingEnvironment = Mock.Of(e => e.ApplicationName == name);
- var compiler = new CSharpCompiler(ReferenceManager, hostingEnvironment);
-
- // Act
- var options = compiler.GetDependencyContextCompilationOptions();
-
- // Assert
- Assert.Same(DependencyContextCompilationOptions.Default, options);
- }
-
- [Fact]
- public void GetCompilationOptions_ReturnsDefaultOptionsIfApplicationDoesNotHaveDependencyContext()
- {
- // Arrange
- var hostingEnvironment = new Mock();
- hostingEnvironment.SetupGet(e => e.ApplicationName)
- .Returns(typeof(Controller).GetTypeInfo().Assembly.GetName().Name);
- var compiler = new CSharpCompiler(ReferenceManager, hostingEnvironment.Object);
-
- // Act
- var options = compiler.GetDependencyContextCompilationOptions();
-
- // Assert
- Assert.Same(DependencyContextCompilationOptions.Default, options);
- }
-
- [Fact]
- public void Constructor_SetsCompilationOptionsFromDependencyContext()
- {
- // Arrange
- var hostingEnvironment = new Mock();
- hostingEnvironment.SetupGet(e => e.ApplicationName)
- .Returns(GetType().GetTypeInfo().Assembly.GetName().Name);
- var compiler = new CSharpCompiler(ReferenceManager, hostingEnvironment.Object);
-
- // Act & Assert
- var parseOptions = compiler.ParseOptions;
- Assert.Contains("SOME_TEST_DEFINE", parseOptions.PreprocessorSymbolNames);
- }
-
- [Theory]
- [InlineData("Development", OptimizationLevel.Debug)]
- [InlineData("Staging", OptimizationLevel.Release)]
- [InlineData("Production", OptimizationLevel.Release)]
- public void Constructor_SetsOptimizationLevelBasedOnEnvironment(
- string environment,
- OptimizationLevel expected)
- {
- // Arrange
- var options = new RazorViewEngineOptions();
- var hostingEnvironment = new Mock();
- hostingEnvironment.SetupGet(e => e.EnvironmentName)
- .Returns(environment);
- var compiler = new CSharpCompiler(ReferenceManager, hostingEnvironment.Object);
-
- // Act & Assert
- var compilationOptions = compiler.CSharpCompilationOptions;
- Assert.Equal(expected, compilationOptions.OptimizationLevel);
- }
-
- [Theory]
- [InlineData("Development", "DEBUG")]
- [InlineData("Staging", "RELEASE")]
- [InlineData("Production", "RELEASE")]
- public void EnsureOptions_SetsPreprocessorSymbols(string environment, string expectedConfiguration)
- {
- // Arrange
- var options = new RazorViewEngineOptions();
- var hostingEnvironment = new Mock();
- hostingEnvironment.SetupGet(e => e.EnvironmentName)
- .Returns(environment);
- var compiler = new CSharpCompiler(ReferenceManager, hostingEnvironment.Object);
-
- // Act & Assert
- var parseOptions = compiler.ParseOptions;
- Assert.Equal(new[] { expectedConfiguration }, parseOptions.PreprocessorSymbolNames);
- }
-
- [Fact]
- public void EnsureOptions_ConfiguresDefaultCompilationOptions()
- {
- // Arrange
- var hostingEnvironment = Mock.Of(h => h.EnvironmentName == "Development");
- var compiler = new CSharpCompiler(ReferenceManager, hostingEnvironment);
-
- // Act & Assert
- var compilationOptions = compiler.CSharpCompilationOptions;
- Assert.False(compilationOptions.AllowUnsafe);
- Assert.Equal(ReportDiagnostic.Default, compilationOptions.GeneralDiagnosticOption);
- Assert.Equal(OptimizationLevel.Debug, compilationOptions.OptimizationLevel);
- Assert.Collection(compilationOptions.SpecificDiagnosticOptions.OrderBy(d => d.Key),
- item =>
- {
- Assert.Equal("CS1701", item.Key);
- Assert.Equal(ReportDiagnostic.Suppress, item.Value);
- },
- item =>
- {
- Assert.Equal("CS1702", item.Key);
- Assert.Equal(ReportDiagnostic.Suppress, item.Value);
- },
- item =>
- {
- Assert.Equal("CS1705", item.Key);
- Assert.Equal(ReportDiagnostic.Suppress, item.Value);
- });
- }
-
- [Fact]
- public void EnsureOptions_ConfiguresDefaultParseOptions()
- {
- // Arrange
- var hostingEnvironment = Mock.Of(h => h.EnvironmentName == "Development");
- var compiler = new CSharpCompiler(ReferenceManager, hostingEnvironment);
-
- // Act & Assert
- var parseOptions = compiler.ParseOptions;
- Assert.Equal(LanguageVersion.CSharp7, parseOptions.LanguageVersion);
- Assert.Equal(new[] { "DEBUG" }, parseOptions.PreprocessorSymbolNames);
- }
-
- [Fact]
- public void Constructor_ConfiguresLanguageVersion()
- {
- // Arrange
- var dependencyContextOptions = new DependencyContextCompilationOptions(
- new[] { "MyDefine" },
- languageVersion: "7.1",
- platform: null,
- allowUnsafe: true,
- warningsAsErrors: null,
- optimize: null,
- keyFile: null,
- delaySign: null,
- publicSign: null,
- debugType: null,
- emitEntryPoint: null,
- generateXmlDocumentation: null);
- var hostingEnvironment = Mock.Of();
-
- var compiler = new TestCSharpCompiler(ReferenceManager, hostingEnvironment, dependencyContextOptions);
-
- // Act & Assert
- var compilationOptions = compiler.ParseOptions;
- Assert.Equal(LanguageVersion.CSharp7_1, compilationOptions.LanguageVersion);
- }
-
-
- [Fact]
- public void EmitOptions_ReadsDebugTypeFromDependencyContext()
- {
- // Arrange
- var dependencyContextOptions = new DependencyContextCompilationOptions(
- new[] { "MyDefine" },
- languageVersion: "7.1",
- platform: null,
- allowUnsafe: true,
- warningsAsErrors: null,
- optimize: null,
- keyFile: null,
- delaySign: null,
- publicSign: null,
- debugType: "portable",
- emitEntryPoint: null,
- generateXmlDocumentation: null);
- var hostingEnvironment = Mock.Of();
-
- var compiler = new TestCSharpCompiler(ReferenceManager, hostingEnvironment, dependencyContextOptions);
-
- // Act & Assert
- var emitOptions = compiler.EmitOptions;
- Assert.Equal(DebugInformationFormat.PortablePdb, emitOptions.DebugInformationFormat);
- Assert.True(compiler.EmitPdb);
- }
-
- [Fact]
- public void EmitOptions_SetsDebugInformationFormatToPortable_WhenDebugTypeIsEmbedded()
- {
- // Arrange
- var dependencyContextOptions = new DependencyContextCompilationOptions(
- new[] { "MyDefine" },
- languageVersion: "7.1",
- platform: null,
- allowUnsafe: true,
- warningsAsErrors: null,
- optimize: null,
- keyFile: null,
- delaySign: null,
- publicSign: null,
- debugType: "embedded",
- emitEntryPoint: null,
- generateXmlDocumentation: null);
- var hostingEnvironment = Mock.Of();
-
- var compiler = new TestCSharpCompiler(ReferenceManager, hostingEnvironment, dependencyContextOptions);
-
- // Act & Assert
- var emitOptions = compiler.EmitOptions;
- Assert.Equal(DebugInformationFormat.PortablePdb, emitOptions.DebugInformationFormat);
- Assert.True(compiler.EmitPdb);
- }
-
- [Fact]
- public void EmitOptions_DoesNotSetEmitPdb_IfDebugTypeIsNone()
- {
- // Arrange
- var dependencyContextOptions = new DependencyContextCompilationOptions(
- new[] { "MyDefine" },
- languageVersion: "7.1",
- platform: null,
- allowUnsafe: true,
- warningsAsErrors: null,
- optimize: null,
- keyFile: null,
- delaySign: null,
- publicSign: null,
- debugType: "none",
- emitEntryPoint: null,
- generateXmlDocumentation: null);
- var hostingEnvironment = Mock.Of();
-
- var compiler = new TestCSharpCompiler(ReferenceManager, hostingEnvironment, dependencyContextOptions);
-
- // Act & Assert
- Assert.False(compiler.EmitPdb);
- }
-
- [Fact]
- public void Constructor_ConfiguresAllowUnsafe()
- {
- // Arrange
- var dependencyContextOptions = new DependencyContextCompilationOptions(
- new[] { "MyDefine" },
- languageVersion: null,
- platform: null,
- allowUnsafe: true,
- warningsAsErrors: null,
- optimize: null,
- keyFile: null,
- delaySign: null,
- publicSign: null,
- debugType: null,
- emitEntryPoint: null,
- generateXmlDocumentation: null);
- var hostingEnvironment = Mock.Of();
-
- var compiler = new TestCSharpCompiler(ReferenceManager, hostingEnvironment, dependencyContextOptions);
-
- // Act & Assert
- var compilationOptions = compiler.CSharpCompilationOptions;
- Assert.True(compilationOptions.AllowUnsafe);
- }
-
- [Fact]
- public void Constructor_SetsDiagnosticOption()
- {
- // Arrange
- var dependencyContextOptions = new DependencyContextCompilationOptions(
- new[] { "MyDefine" },
- languageVersion: null,
- platform: null,
- allowUnsafe: null,
- warningsAsErrors: true,
- optimize: null,
- keyFile: null,
- delaySign: null,
- publicSign: null,
- debugType: null,
- emitEntryPoint: null,
- generateXmlDocumentation: null);
- var hostingEnvironment = Mock.Of();
-
- var compiler = new TestCSharpCompiler(ReferenceManager, hostingEnvironment, dependencyContextOptions);
-
- // Act & Assert
- var compilationOptions = compiler.CSharpCompilationOptions;
- Assert.Equal(ReportDiagnostic.Error, compilationOptions.GeneralDiagnosticOption);
- }
-
- [Fact]
- public void Constructor_SetsOptimizationLevel()
- {
- // Arrange
- var dependencyContextOptions = new DependencyContextCompilationOptions(
- new[] { "MyDefine" },
- languageVersion: null,
- platform: null,
- allowUnsafe: null,
- warningsAsErrors: null,
- optimize: true,
- keyFile: null,
- delaySign: null,
- publicSign: null,
- debugType: null,
- emitEntryPoint: null,
- generateXmlDocumentation: null);
- var hostingEnvironment = Mock.Of();
-
- var compiler = new TestCSharpCompiler(ReferenceManager, hostingEnvironment, dependencyContextOptions);
-
- // Act & Assert
- var compilationOptions = compiler.CSharpCompilationOptions;
- Assert.Equal(OptimizationLevel.Release, compilationOptions.OptimizationLevel);
- }
-
- [Fact]
- public void Constructor_SetsDefines()
- {
- // Arrange
- var dependencyContextOptions = new DependencyContextCompilationOptions(
- new[] { "MyDefine" },
- languageVersion: null,
- platform: null,
- allowUnsafe: null,
- warningsAsErrors: null,
- optimize: true,
- keyFile: null,
- delaySign: null,
- publicSign: null,
- debugType: null,
- emitEntryPoint: null,
- generateXmlDocumentation: null);
- var hostingEnvironment = Mock.Of();
-
- var compiler = new TestCSharpCompiler(ReferenceManager, hostingEnvironment, dependencyContextOptions);
-
- // Act & Assert
- var parseOptions = compiler.ParseOptions;
- Assert.Equal(new[] { "MyDefine", "RELEASE" }, parseOptions.PreprocessorSymbolNames);
- }
-
- [Fact]
- public void Compile_UsesApplicationsCompilationSettings_ForParsingAndCompilation()
- {
- // Arrange
- var content = "public class Test {}";
- var define = "MY_CUSTOM_DEFINE";
- var dependencyContextOptions = new DependencyContextCompilationOptions(
- new[] { define },
- languageVersion: null,
- platform: null,
- allowUnsafe: null,
- warningsAsErrors: null,
- optimize: true,
- keyFile: null,
- delaySign: null,
- publicSign: null,
- debugType: null,
- emitEntryPoint: null,
- generateXmlDocumentation: null);
- var hostingEnvironment = Mock.Of();
- var compiler = new TestCSharpCompiler(ReferenceManager, hostingEnvironment, dependencyContextOptions);
-
- // Act
- var syntaxTree = compiler.CreateSyntaxTree(SourceText.From(content));
-
- // Assert
- Assert.Contains(define, syntaxTree.Options.PreprocessorSymbolNames);
- }
-
- private class TestCSharpCompiler : CSharpCompiler
- {
- private readonly DependencyContextCompilationOptions _options;
-
- public TestCSharpCompiler(
-#pragma warning disable CS0618 // Type or member is obsolete
- RazorReferenceManager referenceManager,
-#pragma warning restore CS0618 // Type or member is obsolete
- IHostingEnvironment hostingEnvironment,
- DependencyContextCompilationOptions options)
- : base(referenceManager, hostingEnvironment)
- {
- _options = options;
- }
-
- protected internal override DependencyContextCompilationOptions GetDependencyContextCompilationOptions()
- => _options;
- }
- }
-}
diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/ChecksumValidatorTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/ChecksumValidatorTest.cs
deleted file mode 100644
index cfbf962d2..000000000
--- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/ChecksumValidatorTest.cs
+++ /dev/null
@@ -1,195 +0,0 @@
-// 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 Microsoft.AspNetCore.Razor.Hosting;
-using Microsoft.AspNetCore.Razor.Language;
-using Xunit;
-using static Microsoft.AspNetCore.Razor.Hosting.TestRazorCompiledItem;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
-{
- public class ChecksumValidatorTest
- {
- public ChecksumValidatorTest()
- {
- ProjectFileSystem = new VirtualRazorProjectFileSystem();
- }
-
- public VirtualRazorProjectFileSystem ProjectFileSystem { get; }
-
- [Fact]
- public void IsRecompilationSupported_NoChecksums_ReturnsFalse()
- {
- // Arrange
- var item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", "/Views/Home/Index.cstml", new object[] { });
-
- // Act
- var result = ChecksumValidator.IsRecompilationSupported(item);
-
- // Assert
- Assert.False(result);
- }
-
- [Fact]
- public void IsRecompilationSupported_NoPrimaryChecksum_ReturnsFalse()
- {
- // Arrange
- var item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", "/Views/Home/Index.cstml", new object[]
- {
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some import"), "/Views/Home/_ViewImports.cstml"),
- });
-
- // Act
- var result = ChecksumValidator.IsRecompilationSupported(item);
-
- // Assert
- Assert.False(result);
- }
-
- [Fact]
- public void IsRecompilationSupported_HasPrimaryChecksum_ReturnsTrue()
- {
- // Arrange
- var item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", "/Views/Home/Index.cstml", new object[]
- {
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some import"), "/Views/Home/_ViewImports.cstml"),
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some content"), "/Views/Home/Index.cstml"),
- });
-
- // Act
- var result = ChecksumValidator.IsRecompilationSupported(item);
-
- // Assert
- Assert.True(result);
- }
-
- [Fact]
- public void IsItemValid_NoChecksums_ReturnsTrue()
- {
- // Arrange
- var item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", "/Views/Home/Index.cstml", new object[] { });
-
- // Act
- var result = ChecksumValidator.IsItemValid(ProjectFileSystem, item);
-
- // Assert
- Assert.True(result);
- }
-
- [Fact]
- public void IsItemValid_NoPrimaryChecksum_ReturnsTrue()
- {
- // Arrange
- var item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", "/Views/Home/Index.cstml", new object[]
- {
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some import"), "/Views/Home/_ViewImports.cstml"),
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some content"), "/Views/Home/About.cstml"),
- });
-
- // Act
- var result = ChecksumValidator.IsItemValid(ProjectFileSystem, item);
-
- // Assert
- Assert.True(result);
- }
-
- [Fact]
- public void IsItemValid_PrimaryFileDoesNotExist_ReturnsTrue()
- {
- // Arrange
- var item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", "/Views/Home/Index.cstml", new object[]
- {
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some import"), "/Views/Home/_ViewImports.cstml"),
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some content"), "/Views/Home/Index.cstml"),
- });
-
- ProjectFileSystem.Add(new TestRazorProjectItem("/Views/Home/_ViewImports.cstml", "dkdkfkdf")); // This will be ignored
-
- // Act
- var result = ChecksumValidator.IsItemValid(ProjectFileSystem, item);
-
- // Assert
- Assert.True(result);
- }
-
- [Fact]
- public void IsItemValid_PrimaryFileExistsButDoesNotMatch_ReturnsFalse()
- {
- // Arrange
- var item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", "/Views/Home/Index.cstml", new object[]
- {
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some import"), "/Views/Home/_ViewImports.cstml"),
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some content"), "/Views/Home/Index.cstml"),
- });
-
- ProjectFileSystem.Add(new TestRazorProjectItem("/Views/Home/Index.cstml", "other content"));
-
- // Act
- var result = ChecksumValidator.IsItemValid(ProjectFileSystem, item);
-
- // Assert
- Assert.False(result);
- }
-
- [Fact]
- public void IsItemValid_ImportFileDoesNotExist_ReturnsFalse()
- {
- // Arrange
- var item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", "/Views/Home/Index.cstml", new object[]
- {
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some import"), "/Views/Home/_ViewImports.cstml"),
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some content"), "/Views/Home/Index.cstml"),
- });
-
- ProjectFileSystem.Add(new TestRazorProjectItem("/Views/Home/Index.cstml", "some content"));
-
- // Act
- var result = ChecksumValidator.IsItemValid(ProjectFileSystem, item);
-
- // Assert
- Assert.False(result);
- }
-
- [Fact]
- public void IsItemValid_ImportFileExistsButDoesNotMatch_ReturnsFalse()
- {
- // Arrange
- var item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", "/Views/Home/Index.cstml", new object[]
- {
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some import"), "/Views/Home/_ViewImports.cstml"),
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some content"), "/Views/Home/Index.cstml"),
- });
-
- ProjectFileSystem.Add(new TestRazorProjectItem("/Views/Home/Index.cstml", "some content"));
- ProjectFileSystem.Add(new TestRazorProjectItem("/Views/Home/_ViewImports.cstml", "some other import"));
-
- // Act
- var result = ChecksumValidator.IsItemValid(ProjectFileSystem, item);
-
- // Assert
- Assert.False(result);
- }
-
- [Fact]
- public void IsItemValid_AllFilesMatch_ReturnsTrue()
- {
- // Arrange
- var item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", "/Views/Home/Index.cstml", new object[]
- {
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some other import"), "/Views/_ViewImports.cstml"),
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some import"), "/Views/Home/_ViewImports.cstml"),
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some content"), "/Views/Home/Index.cstml"),
- });
-
- ProjectFileSystem.Add(new TestRazorProjectItem("/Views/Home/Index.cstml", "some content"));
- ProjectFileSystem.Add(new TestRazorProjectItem("/Views/Home/_ViewImports.cstml", "some import"));
- ProjectFileSystem.Add(new TestRazorProjectItem("/Views/_ViewImports.cstml", "some other import"));
-
- // Act
- var result = ChecksumValidator.IsItemValid(ProjectFileSystem, item);
-
- // Assert
- Assert.True(result);
- }
- }
-}
diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/CompilerFailedExceptionFactoryTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/CompilerFailedExceptionFactoryTest.cs
deleted file mode 100644
index 5cfca9ca3..000000000
--- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/CompilerFailedExceptionFactoryTest.cs
+++ /dev/null
@@ -1,355 +0,0 @@
-// 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.IO;
-using System.Linq;
-using System.Text;
-using Microsoft.AspNetCore.Mvc.Razor.Extensions;
-using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.Text;
-using Xunit;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
-{
- public class CompilerFailedExceptionFactoryTest
- {
- [Fact]
- public void GetCompilationFailedResult_ReadsRazorErrorsFromPage()
- {
- // Arrange
- var viewPath = "/Views/Home/Index.cshtml";
-
- var fileSystem = new VirtualRazorProjectFileSystem();
- fileSystem.Add(new TestRazorProjectItem(viewPath, ""));
-
- var razorEngine = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem).Engine;
-
- var templateEngine = new MvcRazorTemplateEngine(razorEngine, fileSystem);
- var codeDocument = templateEngine.CreateCodeDocument(viewPath);
-
- // Act
- var csharpDocument = templateEngine.GenerateCode(codeDocument);
- var compilationResult = CompilationFailedExceptionFactory.Create(codeDocument, csharpDocument.Diagnostics);
-
- // Assert
- var failure = Assert.Single(compilationResult.CompilationFailures);
- Assert.Equal(viewPath, failure.SourceFilePath);
- Assert.Collection(failure.Messages,
- message => Assert.StartsWith(
- @"Unterminated string literal.",
- message.Message),
- message => Assert.StartsWith(
- @"The explicit expression block is missing a closing "")"" character.",
- message.Message));
- }
-
- [Fact]
- public void GetCompilationFailedResult_WithMissingReferences()
- {
- // Arrange
- var expected = "One or more compilation references may be missing. If you're seeing this in a published application, set 'CopyRefAssembliesToPublishDirectory' to true in your project file to ensure files in the refs directory are published.";
- var compilation = CSharpCompilation.Create("Test", options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
- var syntaxTree = CSharpSyntaxTree.ParseText("@class Test { public string Test { get; set; } }");
- compilation = compilation.AddSyntaxTrees(syntaxTree);
- var emitResult = compilation.Emit(new MemoryStream());
-
- // Act
- var exception = CompilationFailedExceptionFactory.Create(
- RazorCodeDocument.Create(RazorSourceDocument.Create("Test", "Index.cshtml"), Enumerable.Empty()),
- syntaxTree.ToString(),
- "Test",
- emitResult.Diagnostics);
-
- // Assert
- Assert.Collection(
- exception.CompilationFailures,
- failure => Assert.Equal(expected, failure.FailureSummary));
- }
-
- [Fact]
- public void GetCompilationFailedResult_UsesPhysicalPath()
- {
- // Arrange
- var viewPath = "/Views/Home/Index.cshtml";
- var physicalPath = @"x:\myapp\views\home\index.cshtml";
-
- var fileSystem = new VirtualRazorProjectFileSystem();
- fileSystem.Add(new TestRazorProjectItem(viewPath, "", physicalPath: physicalPath));
-
- var razorEngine = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem).Engine;
- var templateEngine = new MvcRazorTemplateEngine(razorEngine, fileSystem);
-
- var codeDocument = templateEngine.CreateCodeDocument(viewPath);
-
- // Act
- var csharpDocument = templateEngine.GenerateCode(codeDocument);
- var compilationResult = CompilationFailedExceptionFactory.Create(codeDocument, csharpDocument.Diagnostics);
-
- // Assert
- var failure = Assert.Single(compilationResult.CompilationFailures);
- Assert.Equal(physicalPath, failure.SourceFilePath);
- }
-
- [Fact]
- public void GetCompilationFailedResult_ReadsContentFromSourceDocuments()
- {
- // Arrange
- var viewPath = "/Views/Home/Index.cshtml";
- var fileContent =
-@"
-@if (User.IsAdmin)
-{
-
-}
-";
-
- var fileSystem = new VirtualRazorProjectFileSystem();
- fileSystem.Add(new TestRazorProjectItem(viewPath, fileContent));
-
- var razorEngine = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem).Engine;
- var templateEngine = new MvcRazorTemplateEngine(razorEngine, fileSystem);
-
- var codeDocument = templateEngine.CreateCodeDocument(viewPath);
-
- // Act
- var csharpDocument = templateEngine.GenerateCode(codeDocument);
- var compilationResult = CompilationFailedExceptionFactory.Create(codeDocument, csharpDocument.Diagnostics);
-
- // Assert
- var failure = Assert.Single(compilationResult.CompilationFailures);
- Assert.Equal(fileContent, failure.SourceFileContent);
- }
-
- [Fact]
- public void GetCompilationFailedResult_ReadsContentFromImports()
- {
- // Arrange
- var viewPath = "/Views/Home/Index.cshtml";
- var importsPath = "/Views/_MyImports.cshtml";
- var fileContent = "@ ";
- var importsContent = "@(abc";
-
- var fileSystem = new VirtualRazorProjectFileSystem();
- fileSystem.Add(new TestRazorProjectItem(viewPath, fileContent));
- fileSystem.Add(new TestRazorProjectItem("/Views/_MyImports.cshtml", importsContent));
-
- var razorEngine = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem).Engine;
- var templateEngine = new MvcRazorTemplateEngine(razorEngine, fileSystem)
- {
- Options =
- {
- ImportsFileName = "_MyImports.cshtml",
- }
- };
- var codeDocument = templateEngine.CreateCodeDocument(viewPath);
-
- // Act
- var csharpDocument = templateEngine.GenerateCode(codeDocument);
- var compilationResult = CompilationFailedExceptionFactory.Create(codeDocument, csharpDocument.Diagnostics);
-
- // Assert
- Assert.Collection(
- compilationResult.CompilationFailures,
- failure =>
- {
- Assert.Equal(viewPath, failure.SourceFilePath);
- Assert.Collection(failure.Messages,
- message =>
- {
- Assert.Equal(@"A space or line break was encountered after the ""@"" character. Only valid identifiers, keywords, comments, ""("" and ""{"" are valid at the start of a code block and they must occur immediately following ""@"" with no space in between.",
- message.Message);
- });
- },
- failure =>
- {
- Assert.Equal(importsPath, failure.SourceFilePath);
- Assert.Collection(failure.Messages,
- message =>
- {
- Assert.Equal(@"The explicit expression 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.",
- message.Message);
- });
- });
- }
-
- [Fact]
- public void GetCompilationFailedResult_GroupsMessages()
- {
- // Arrange
- var viewPath = "views/index.razor";
- var viewImportsPath = "views/global.import.cshtml";
- var codeDocument = RazorCodeDocument.Create(
- Create(viewPath, "View Content"),
- new[] { Create(viewImportsPath, "Global Import Content") });
- var diagnostics = new[]
- {
- GetRazorDiagnostic("message-1", new SourceLocation(1, 2, 17), length: 1),
- GetRazorDiagnostic("message-2", new SourceLocation(viewPath, 1, 4, 6), length: 7),
- GetRazorDiagnostic("message-3", SourceLocation.Undefined, length: -1),
- GetRazorDiagnostic("message-4", new SourceLocation(viewImportsPath, 1, 3, 8), length: 4),
- };
-
- // Act
- var result = CompilationFailedExceptionFactory.Create(codeDocument, diagnostics);
-
- // Assert
- Assert.Collection(result.CompilationFailures,
- failure =>
- {
- Assert.Equal(viewPath, failure.SourceFilePath);
- Assert.Equal("View Content", failure.SourceFileContent);
- Assert.Collection(failure.Messages,
- message =>
- {
- Assert.Equal(diagnostics[0].GetMessage(), message.Message);
- Assert.Equal(viewPath, message.SourceFilePath);
- Assert.Equal(3, message.StartLine);
- Assert.Equal(17, message.StartColumn);
- Assert.Equal(3, message.EndLine);
- Assert.Equal(18, message.EndColumn);
- },
- message =>
- {
- Assert.Equal(diagnostics[1].GetMessage(), message.Message);
- Assert.Equal(viewPath, message.SourceFilePath);
- Assert.Equal(5, message.StartLine);
- Assert.Equal(6, message.StartColumn);
- Assert.Equal(5, message.EndLine);
- Assert.Equal(13, message.EndColumn);
- },
- message =>
- {
- Assert.Equal(diagnostics[2].GetMessage(), message.Message);
- Assert.Equal(viewPath, message.SourceFilePath);
- Assert.Equal(0, message.StartLine);
- Assert.Equal(-1, message.StartColumn);
- Assert.Equal(0, message.EndLine);
- Assert.Equal(-2, message.EndColumn);
- });
- },
- failure =>
- {
- Assert.Equal(viewImportsPath, failure.SourceFilePath);
- Assert.Equal("Global Import Content", failure.SourceFileContent);
- Assert.Collection(failure.Messages,
- message =>
- {
- Assert.Equal(diagnostics[3].GetMessage(), message.Message);
- Assert.Equal(viewImportsPath, message.SourceFilePath);
- Assert.Equal(4, message.StartLine);
- Assert.Equal(8, message.StartColumn);
- Assert.Equal(4, message.EndLine);
- Assert.Equal(12, message.EndColumn);
- });
- });
- }
-
- [Fact]
- public void GetCompilationFailedResult_ReturnsCompilationResult_WithGroupedMessages()
- {
- // Arrange
- var viewPath = "Views/Home/Index";
- var generatedCodeFileName = "Generated Code";
- var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.Create("view-content", viewPath));
- var assemblyName = "random-assembly-name";
-
- var diagnostics = new[]
- {
- Diagnostic.Create(
- GetRoslynDiagnostic("message-1"),
- Location.Create(
- viewPath,
- new TextSpan(10, 5),
- new LinePositionSpan(new LinePosition(10, 1), new LinePosition(10, 2)))),
- Diagnostic.Create(
- GetRoslynDiagnostic("message-2"),
- Location.Create(
- assemblyName,
- new TextSpan(1, 6),
- new LinePositionSpan(new LinePosition(1, 2), new LinePosition(3, 4)))),
- Diagnostic.Create(
- GetRoslynDiagnostic("message-3"),
- Location.Create(
- viewPath,
- new TextSpan(40, 50),
- new LinePositionSpan(new LinePosition(30, 5), new LinePosition(40, 12)))),
- };
-
- // Act
- var compilationResult = CompilationFailedExceptionFactory.Create(
- codeDocument,
- "compilation-content",
- assemblyName,
- diagnostics);
-
- // Assert
- Assert.Collection(compilationResult.CompilationFailures,
- failure =>
- {
- Assert.Equal(viewPath, failure.SourceFilePath);
- Assert.Equal("view-content", failure.SourceFileContent);
- Assert.Collection(failure.Messages,
- message =>
- {
- Assert.Equal("message-1", message.Message);
- Assert.Equal(viewPath, message.SourceFilePath);
- Assert.Equal(11, message.StartLine);
- Assert.Equal(2, message.StartColumn);
- Assert.Equal(11, message.EndLine);
- Assert.Equal(3, message.EndColumn);
- },
- message =>
- {
- Assert.Equal("message-3", message.Message);
- Assert.Equal(viewPath, message.SourceFilePath);
- Assert.Equal(31, message.StartLine);
- Assert.Equal(6, message.StartColumn);
- Assert.Equal(41, message.EndLine);
- Assert.Equal(13, message.EndColumn);
- });
- },
- failure =>
- {
- Assert.Equal(generatedCodeFileName, failure.SourceFilePath);
- Assert.Equal("compilation-content", failure.SourceFileContent);
- Assert.Collection(failure.Messages,
- message =>
- {
- Assert.Equal("message-2", message.Message);
- Assert.Equal(assemblyName, message.SourceFilePath);
- Assert.Equal(2, message.StartLine);
- Assert.Equal(3, message.StartColumn);
- Assert.Equal(4, message.EndLine);
- Assert.Equal(5, message.EndColumn);
- });
- });
- }
-
- private static RazorSourceDocument Create(string path, string template)
- {
- var stream = new MemoryStream(Encoding.UTF8.GetBytes(template));
- return RazorSourceDocument.ReadFrom(stream, path);
- }
-
- private static RazorDiagnostic GetRazorDiagnostic(string message, SourceLocation sourceLocation, int length)
- {
- var diagnosticDescriptor = new RazorDiagnosticDescriptor("test-id", () => message, RazorDiagnosticSeverity.Error);
- var sourceSpan = new SourceSpan(sourceLocation, length);
-
- return RazorDiagnostic.Create(diagnosticDescriptor, sourceSpan);
- }
-
- private static DiagnosticDescriptor GetRoslynDiagnostic(string messageFormat)
- {
- return new DiagnosticDescriptor(
- id: "someid",
- title: "sometitle",
- messageFormat: messageFormat,
- category: "some-category",
- defaultSeverity: DiagnosticSeverity.Error,
- isEnabledByDefault: true);
- }
- }
-}
diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/DefaultRazorReferenceManagerTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/DefaultRazorReferenceManagerTest.cs
deleted file mode 100644
index 6e634fd96..000000000
--- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/DefaultRazorReferenceManagerTest.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-// 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.Linq;
-using System.Reflection;
-using Microsoft.AspNetCore.Mvc.ApplicationParts;
-using Microsoft.CodeAnalysis;
-using Microsoft.Extensions.Options;
-using Xunit;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
-{
-#pragma warning disable CS0618 // Type or member is obsolete
- public class DefaultRazorReferenceManagerTest
- {
- [Fact]
- public void GetCompilationReferences_CombinesApplicationPartAndOptionMetadataReferences()
- {
- // Arrange
- var options = new RazorViewEngineOptions();
- var objectAssemblyLocation = typeof(object).GetTypeInfo().Assembly.Location;
- var objectAssemblyMetadataReference = MetadataReference.CreateFromFile(objectAssemblyLocation);
- options.AdditionalCompilationReferences.Add(objectAssemblyMetadataReference);
-
- var applicationPartManager = GetApplicationPartManager();
- var feature = new MetadataReferenceFeature();
- applicationPartManager.PopulateFeature(feature);
- var partReferences = feature.MetadataReferences;
- var expectedReferenceDisplays = partReferences
- .Concat(new[] { objectAssemblyMetadataReference })
- .Select(r => r.Display);
- var referenceManager = new DefaultRazorReferenceManager(
- applicationPartManager,
- Options.Create(options));
-
- // Act
- var references = referenceManager.CompilationReferences;
- var referenceDisplays = references.Select(reference => reference.Display);
-
- // Assert
- Assert.Equal(expectedReferenceDisplays, referenceDisplays);
- }
-
- private static ApplicationPartManager GetApplicationPartManager()
- {
- var applicationPartManager = new ApplicationPartManager();
- var assembly = typeof(DefaultRazorReferenceManagerTest).GetTypeInfo().Assembly;
- applicationPartManager.ApplicationParts.Add(new AssemblyPart(assembly));
- applicationPartManager.FeatureProviders.Add(new MetadataReferenceFeatureProvider());
-
- return applicationPartManager;
- }
- }
-#pragma warning restore CS0618 // Type or member is obsolete
-}
diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/ExpressionRewriterTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/ExpressionRewriterTest.cs
deleted file mode 100644
index 7dd6bc25d..000000000
--- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/ExpressionRewriterTest.cs
+++ /dev/null
@@ -1,576 +0,0 @@
-// 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.Linq;
-using System.Reflection;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using Xunit;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
-{
- public class ExpressionRewriterTest
- {
- [Fact]
- public void ExpressionRewriter_DoesNotThrowsOnUnknownTypes()
- {
- // Arrange
- var source = @"
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.AspNetCore.Mvc.Razor;
-
-public class ExamplePage : RazorPage
-{
- public IViewComponentHelper Component { get; set; }
-
- public override async Task ExecuteAsync()
- {
- Write(
- await Component.InvokeAsync(
- ""SomeComponent"",
- item => new HelperResult((__razor_template_writer) => WriteLiteralTo(__razor_template_writer, ""Hello World""))));
- }
- }
-";
- var tree = CSharpSyntaxTree.ParseText(source);
-
- // Allow errors here because of an anomaly where Roslyn (depending on code sample) will finish compilation
- // without diagnostic errors. This test case replicates that scenario by allowing a semantic model with
- // errors to be visited by the expression rewriter to validate unexpected exceptions aren't thrown.
- // Error created: "Cannot convert lambda expression to type 'object' because it is not a delegate type."
- var compilation = Compile(tree, allowErrors: true);
- var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true);
- var rewriter = new ExpressionRewriter(semanticModel);
- var root = tree.GetRoot();
-
- // Act
- var result = rewriter.Visit(root);
-
- // Assert
- Assert.True(root.IsEquivalentTo(result));
- }
-
- [Fact]
- public void ExpressionRewriter_CanRewriteExpression_IdentityExpression()
- {
- // Arrange
- var source = @"
-using System;
-using System.Linq.Expressions;
-public class Program
-{
- public static void CalledWithExpression(Expression> expression)
- {
- }
-
- public static void Main(string[] args)
- {
- CalledWithExpression(x => x);
- }
-}
-";
-
- var tree = CSharpSyntaxTree.ParseText(source);
- var compilation = Compile(tree);
- var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true);
-
- var rewriter = new ExpressionRewriter(semanticModel);
-
- // Act
- var result = rewriter.Visit(tree.GetRoot());
-
- // Assert
- var fields = FindFields(result);
-
- var field = Assert.Single(fields);
- Assert.Collection(
- field.Modifiers,
- m => Assert.Equal("private", m.ToString()),
- m => Assert.Equal("static", m.ToString()),
- m => Assert.Equal("readonly", m.ToString()));
-
- var declaration = field.Declaration;
- Assert.Equal(
- "global::System.Linq.Expressions.Expression>",
- declaration.Type.ToString());
-
- var variable = Assert.Single(declaration.Variables);
- Assert.Equal("__h0", variable.Identifier.ToString());
- Assert.Equal("x => x", variable.Initializer.Value.ToString());
-
- var arguments = FindArguments(result);
- var argument = Assert.IsType(Assert.Single(arguments.Arguments).Expression);
- Assert.Equal("__h0", argument.Identifier.ToString());
- }
-
- [Fact]
- public void ExpressionRewriter_CanRewriteExpression_MemberAccessExpression()
- {
- // Arrange
- var source = @"
-using System;
-using System.Linq.Expressions;
-public class Program
-{
- public static void CalledWithExpression(Expression> expression)
- {
- }
-
- public static void Main(string[] args)
- {
- CalledWithExpression(x => x.Name);
- }
-}
-
-public class Person
-{
- public string Name { get; set; }
-}
-";
-
- var tree = CSharpSyntaxTree.ParseText(source);
- var compilation = Compile(tree);
- var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true);
-
- var rewriter = new ExpressionRewriter(semanticModel);
-
- // Act
- var result = rewriter.Visit(tree.GetRoot());
-
- // Assert
- var fields = FindFields(result);
-
- var field = Assert.Single(fields);
- Assert.Collection(
- field.Modifiers,
- m => Assert.Equal("private", m.ToString()),
- m => Assert.Equal("static", m.ToString()),
- m => Assert.Equal("readonly", m.ToString()));
-
- var declaration = field.Declaration;
- Assert.Equal(
- "global::System.Linq.Expressions.Expression>",
- declaration.Type.ToString());
-
- var variable = Assert.Single(declaration.Variables);
- Assert.Equal("__h0", variable.Identifier.ToString());
- Assert.Equal("x => x.Name", variable.Initializer.Value.ToString());
-
- var arguments = FindArguments(result);
- var argument = Assert.IsType(Assert.Single(arguments.Arguments).Expression);
- Assert.Equal("__h0", argument.Identifier.ToString());
- }
-
- [Fact]
- public void ExpressionRewriter_CanRewriteExpression_ChainedMemberAccessExpression()
- {
- // Arrange
- var source = @"
-using System;
-using System.Linq.Expressions;
-public class Program
-{
- public static void CalledWithExpression(Expression> expression)
- {
- }
-
- public static void Main(string[] args)
- {
- CalledWithExpression(x => x.Name.Length);
- }
-}
-
-public class Person
-{
- public string Name { get; set; }
-}
-";
-
- var tree = CSharpSyntaxTree.ParseText(source);
- var compilation = Compile(tree);
- var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true);
-
- var rewriter = new ExpressionRewriter(semanticModel);
-
- // Act
- var result = rewriter.Visit(tree.GetRoot());
-
- // Assert
- var fields = FindFields(result);
-
- var field = Assert.Single(fields);
- Assert.Collection(
- field.Modifiers,
- m => Assert.Equal("private", m.ToString()),
- m => Assert.Equal("static", m.ToString()),
- m => Assert.Equal("readonly", m.ToString()));
-
- var declaration = field.Declaration;
- Assert.Equal(
- "global::System.Linq.Expressions.Expression>",
- declaration.Type.ToString());
-
- var variable = Assert.Single(declaration.Variables);
- Assert.Equal("__h0", variable.Identifier.ToString());
- Assert.Equal("x => x.Name.Length", variable.Initializer.Value.ToString());
-
- var arguments = FindArguments(result);
- var argument = Assert.IsType(Assert.Single(arguments.Arguments).Expression);
- Assert.Equal("__h0", argument.Identifier.ToString());
- }
-
- [Fact]
- public void ExpressionRewriter_CannotRewriteExpression_MethodCall()
- {
- // Arrange
- var source = @"
-using System;
-using System.Linq.Expressions;
-public class Program
-{
- public static void CalledWithExpression(Expression> expression)
- {
- }
-
- public static void Main(string[] args)
- {
- CalledWithExpression(x => x.GetHashCode());
- }
-}
-";
-
- var tree = CSharpSyntaxTree.ParseText(source);
- var compilation = Compile(tree);
- var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true);
-
- var rewriter = new ExpressionRewriter(semanticModel);
-
- // Act
- var result = rewriter.Visit(tree.GetRoot());
-
- // Assert
- Assert.Empty(FindFields(result));
- }
-
- [Fact]
- public void ExpressionRewriter_CannotRewriteExpression_NonArgument()
- {
- // Arrange
- var source = @"
-using System;
-using System.Linq.Expressions;
-public class Program
-{
- public static void CalledWithExpression(Expression> expression)
- {
- }
-
- public static void Main(string[] args)
- {
- Expression> expr = x => x.GetHashCode();
- CalledWithExpression(expr);
- }
-}
-";
-
- var tree = CSharpSyntaxTree.ParseText(source);
- var compilation = Compile(tree);
- var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true);
-
- var rewriter = new ExpressionRewriter(semanticModel);
-
- // Act
- var result = rewriter.Visit(tree.GetRoot());
-
- // Assert
- Assert.Empty(FindFields(result));
- }
-
- [Fact]
- public void ExpressionRewriter_CannotRewriteExpression_NestedClass()
- {
- // Arrange
- var source = @"
-using System;
-using System.Linq.Expressions;
-public class Program
-{
- private class Nested
- {
- public static void CalledWithExpression(Expression> expression)
- {
- }
-
- public static void Main(string[] args)
- {
- Expression> expr = x => x.GetHashCode();
- CalledWithExpression(expr);
- }
- }
-}
-";
-
- var tree = CSharpSyntaxTree.ParseText(source);
- var compilation = Compile(tree);
- var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true);
-
- var rewriter = new ExpressionRewriter(semanticModel);
-
- // Act
- var result = rewriter.Visit(tree.GetRoot());
-
- // Assert
- Assert.Empty(FindFields(result));
- }
-
- [Fact]
- public void ExpressionRewriter_CanRewriteExpression_AdditionalArguments()
- {
- // Arrange
- var source = @"
-using System;
-using System.Linq.Expressions;
-public class Program
-{
- public static void CalledWithExpression(int x, Expression> expression, string name)
- {
- }
-
- public static void Main(string[] args)
- {
- CalledWithExpression(5, x => x, ""Billy"");
- }
-}
-";
-
- var tree = CSharpSyntaxTree.ParseText(source);
- var compilation = Compile(tree);
- var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true);
-
- var rewriter = new ExpressionRewriter(semanticModel);
-
- // Act
- var result = rewriter.Visit(tree.GetRoot());
-
- // Assert
- var fields = FindFields(result);
-
- var field = Assert.Single(fields);
- Assert.Collection(
- field.Modifiers,
- m => Assert.Equal("private", m.ToString()),
- m => Assert.Equal("static", m.ToString()),
- m => Assert.Equal("readonly", m.ToString()));
-
- var declaration = field.Declaration;
- Assert.Equal(
- "global::System.Linq.Expressions.Expression>",
- declaration.Type.ToString());
-
- var variable = Assert.Single(declaration.Variables);
- Assert.Equal("__h0", variable.Identifier.ToString());
- Assert.Equal("x => x", variable.Initializer.Value.ToString());
-
- var arguments = FindArguments(result);
- Assert.Equal(3, arguments.Arguments.Count);
- var argument = Assert.IsType(arguments.Arguments[1].Expression);
- Assert.Equal("__h0", argument.Identifier.ToString());
- }
-
- // When we rewrite the expression, we want to maintain the original span as much as possible.
- [Fact]
- public void ExpressionRewriter_CanRewriteExpression_SimpleFormatting()
- {
- // Arrange
- var source = @"
-using System;
-using System.Linq.Expressions;
-public class Program
-{
- public static void CalledWithExpression(Expression> expression)
- {
- }
-
- public static void Main(string[] args)
- {
- CalledWithExpression(x => x.Name.Length);
- }
-}
-
-public class Person
-{
- public string Name { get; set; }
-}
-";
-
- var tree = CSharpSyntaxTree.ParseText(source);
-
- var originalArguments = FindArguments(tree.GetRoot());
- var originalSpan = originalArguments.GetLocation().GetMappedLineSpan();
-
- var compilation = Compile(tree);
- var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true);
-
- var rewriter = new ExpressionRewriter(semanticModel);
-
- // Act
- var result = rewriter.Visit(tree.GetRoot());
-
- // Assert
- var arguments = FindArguments(result);
- Assert.Equal(originalSpan, arguments.GetLocation().GetMappedLineSpan());
- }
-
- // When we rewrite the expression, we want to maintain the original span as much as possible.
- [Fact]
- public void ExpressionRewriter_CanRewriteExpression_ComplexFormatting()
- {
- // Arrange
- var source = @"
-using System;
-using System.Linq.Expressions;
-public class Program
-{
- public static void CalledWithExpression(int z, Expression> expression)
- {
- }
-
- public static void Main(string[] args)
- {
- CalledWithExpression(
- 17,
- x =>
- x.Name.
- Length
- );
- }
-}
-
-public class Person
-{
- public string Name { get; set; }
-}
-";
-
- var tree = CSharpSyntaxTree.ParseText(source);
-
- var originalArguments = FindArguments(tree.GetRoot());
- var originalSpan = originalArguments.GetLocation().GetMappedLineSpan();
-
- var compilation = Compile(tree);
- var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true);
-
- var rewriter = new ExpressionRewriter(semanticModel);
-
- // Act
- var result = rewriter.Visit(tree.GetRoot());
-
- // Assert
- var arguments = FindArguments(result);
- Assert.Equal(originalSpan, arguments.GetLocation().GetMappedLineSpan());
- }
-
- [Fact]
- public void ExpressionRewriter_CanRewriteExpression_BadlyIndentedFormatting()
- {
- // Arrange
- var source = @"
-using System;
-using System.Linq.Expressions;
-public class Program
-{
- public static void CalledWithExpression(Expression> expression)
- {
- }
-
- public static void Main(string[] args)
- {
- CalledWithExpression(x =>
- x.Name.
- Length);
- }
-}
-
-public class Person
-{
- public string Name { get; set; }
-}
-";
-
- var tree = CSharpSyntaxTree.ParseText(source);
-
- var originalArguments = FindArguments(tree.GetRoot());
- var originalSpan = originalArguments.GetLocation().GetMappedLineSpan();
-
- var compilation = Compile(tree);
- var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true);
-
- var rewriter = new ExpressionRewriter(semanticModel);
-
- // Act
- var result = rewriter.Visit(tree.GetRoot());
-
- // Assert
- var arguments = FindArguments(result);
- Assert.Equal(originalSpan, arguments.GetLocation().GetMappedLineSpan());
- }
-
- public ArgumentListSyntax FindArguments(SyntaxNode node)
- {
- return node
- .DescendantNodes(n => true)
- .Where(n => n.IsKind(SyntaxKind.ArgumentList))
- .Cast()
- .Single();
- }
-
- public IEnumerable FindFields(SyntaxNode node)
- {
- return node
- .DescendantNodes(n => true)
- .Where(n => n.IsKind(SyntaxKind.FieldDeclaration))
- .Cast();
- }
-
- private CSharpCompilation Compile(SyntaxTree tree, bool allowErrors = false)
- {
- // Disable 1702 until roslyn turns this off by default
- var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
- .WithSpecificDiagnosticOptions(new Dictionary
- {
- { "CS1701", ReportDiagnostic.Suppress }, // Binding redirects
- { "CS1702", ReportDiagnostic.Suppress },
- { "CS1705", ReportDiagnostic.Suppress }
- });
-
- var compilation = CSharpCompilation.Create(
- "Test.Assembly",
- new[] { tree },
- GetReferences(),
- options: options);
-
- if (!allowErrors)
- {
- var diagnostics = compilation.GetDiagnostics();
- Assert.True(diagnostics.Length == 0, string.Join(Environment.NewLine, diagnostics));
- }
-
- return compilation;
- }
-
- private IEnumerable GetReferences()
- {
- var types = new[]
- {
- typeof(System.Linq.Expressions.Expression),
- typeof(string),
- };
-
- return types.Select(t => MetadataReference.CreateFromFile(t.GetTypeInfo().Assembly.Location));
- }
- }
-}
diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/MetadataReferenceFeatureProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/MetadataReferenceFeatureProviderTest.cs
deleted file mode 100644
index 8f9653c70..000000000
--- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/MetadataReferenceFeatureProviderTest.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-// 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
-{
-#pragma warning disable CS0618 // Type or member is obsolete
- 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_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));
- }
- }
-#pragma warning restore CS0618 // Type or member is obsolete
-}
diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/RazorViewCompilerProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/RazorViewCompilerProviderTest.cs
deleted file mode 100644
index e6e23255b..000000000
--- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/RazorViewCompilerProviderTest.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-// 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 Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.Mvc.ApplicationParts;
-using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.Extensions.FileProviders;
-using Microsoft.Extensions.Logging.Abstractions;
-using Microsoft.Extensions.Options;
-using Moq;
-using Xunit;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
-{
- public class RazorViewCompilerProviderTest
- {
- [Fact]
- public void GetCompiler_ThrowsIfNullFileProvider()
- {
- // Arrange
- var expected =
- $"'{typeof(RazorViewEngineOptions).FullName}.{nameof(RazorViewEngineOptions.FileProviders)}' must " +
- $"not be empty. At least one '{typeof(IFileProvider).FullName}' is required to locate a view for " +
- "rendering.";
- var fileProvider = new NullFileProvider();
- var accessor = Mock.Of(a => a.FileProvider == fileProvider);
-
- var partManager = new ApplicationPartManager();
- var options = Options.Create(new RazorViewEngineOptions());
-
- var referenceManager = new DefaultRazorReferenceManager(partManager, options);
-
- var provider = new RazorViewCompilerProvider(
- partManager,
- RazorProjectEngine.Create(
- RazorConfiguration.Default,
- new FileProviderRazorProjectFileSystem(accessor, Mock.Of())),
- accessor,
- new CSharpCompiler(referenceManager, Mock.Of()),
- options,
- new RazorViewCompilationMemoryCacheProvider(),
- NullLoggerFactory.Instance);
-
- // Act & Assert
- var exception = Assert.Throws(
- () => provider.GetCompiler());
- Assert.Equal(expected, exception.Message);
- }
- }
-}
diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/RazorViewCompilerTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/RazorViewCompilerTest.cs
index 2fb6d3d40..ac26f8e66 100644
--- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/RazorViewCompilerTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Compilation/RazorViewCompilerTest.cs
@@ -3,22 +3,9 @@
using System;
using System.Collections.Generic;
-using System.Threading;
using System.Threading.Tasks;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.Mvc.ApplicationParts;
-using Microsoft.AspNetCore.Mvc.Razor.Extensions;
-using Microsoft.AspNetCore.Razor.Hosting;
-using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.Emit;
-using Microsoft.Extensions.Caching.Memory;
-using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging.Abstractions;
-using Microsoft.Extensions.Options;
-using Moq;
using Xunit;
-using static Microsoft.AspNetCore.Razor.Hosting.TestRazorCompiledItem;
namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
{
@@ -29,249 +16,51 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
{
// Arrange
var path = "/file/does-not-exist";
- var fileProvider = new TestFileProvider();
- var viewCompiler = GetViewCompiler(fileProvider);
+ var viewCompiler = GetViewCompiler();
// Act
var result1 = await viewCompiler.CompileAsync(path);
var result2 = await viewCompiler.CompileAsync(path);
// Assert
- Assert.Same(result1, result2);
Assert.Null(result1.ViewAttribute);
Assert.Empty(result1.ExpirationTokens);
}
[Fact]
- public async Task CompileAsync_ReturnsResultWithExpirationToken_WhenWatchingForFileChanges()
- {
- // Arrange
- var path = "/file/does-not-exist";
- var fileProvider = new TestFileProvider();
- var viewCompiler = GetViewCompiler(fileProvider);
- viewCompiler.AllowRecompilingViewsOnFileChange = true;
-
- // Act
- var result1 = await viewCompiler.CompileAsync(path);
- var result2 = await viewCompiler.CompileAsync(path);
-
- // Assert
- Assert.Same(result1, result2);
- Assert.Null(result1.ViewAttribute);
- Assert.Collection(
- result1.ExpirationTokens,
- token => Assert.Equal(fileProvider.GetChangeToken(path), token));
- }
-
- [Fact]
- public async Task CompileAsync_AddsChangeTokensForViewStartsIfFileExists()
- {
- // Arrange
- var path = "/file/exists/FilePath.cshtml";
- var fileProvider = new TestFileProvider();
- fileProvider.AddFile(path, "Content");
- var viewCompiler = GetViewCompiler(fileProvider);
-
- // Act
- var result = await viewCompiler.CompileAsync(path);
-
- // Assert
- Assert.NotNull(result.ViewAttribute);
- Assert.Empty(result.ExpirationTokens);
- }
-
- [Fact]
- public async Task CompileAsync_AddsChangeTokensForViewStartsIfFileExists_WhenWatchingForFileChanges()
- {
- // Arrange
- var path = "/file/exists/FilePath.cshtml";
- var fileProvider = new TestFileProvider();
- fileProvider.AddFile(path, "Content");
- var viewCompiler = GetViewCompiler(fileProvider);
- viewCompiler.AllowRecompilingViewsOnFileChange = true;
-
- // Act
- var result = await viewCompiler.CompileAsync(path);
-
- // Assert
- Assert.NotNull(result.ViewAttribute);
- Assert.Collection(
- result.ExpirationTokens,
- token => Assert.Same(fileProvider.GetChangeToken(path), token),
- token => Assert.Same(fileProvider.GetChangeToken("/_ViewImports.cshtml"), token),
- token => Assert.Same(fileProvider.GetChangeToken("/file/_ViewImports.cshtml"), token),
- token => Assert.Same(fileProvider.GetChangeToken("/file/exists/_ViewImports.cshtml"), token));
- }
-
- [Theory]
- [InlineData("/Areas/Finances/Views/Home/Index.cshtml")]
- [InlineData(@"Areas\Finances\Views\Home\Index.cshtml")]
- [InlineData(@"\Areas\Finances\Views\Home\Index.cshtml")]
- [InlineData(@"\Areas\Finances\Views/Home\Index.cshtml")]
- public async Task CompileAsync_NormalizesPathSeparatorForPaths(string relativePath)
- {
- // Arrange
- var viewPath = "/Areas/Finances/Views/Home/Index.cshtml";
- var fileProvider = new TestFileProvider();
- fileProvider.AddFile(viewPath, "some content");
- var viewCompiler = GetViewCompiler(fileProvider);
-
- // Act - 1
- var result1 = await viewCompiler.CompileAsync(@"Areas\Finances\Views\Home\Index.cshtml");
-
- // Act - 2
- viewCompiler.Compile = _ => throw new Exception("Can't call me");
- var result2 = await viewCompiler.CompileAsync(relativePath);
-
- // Assert - 2
- Assert.Same(result1, result2);
- }
-
- [Fact]
- public async Task CompileAsync_DoesNotInvalidCache_IfChangeTokenChanges()
+ public async Task CompileAsync_ReturnsCompiledViews()
{
// Arrange
var path = "/Views/Home/Index.cshtml";
- var fileProvider = new TestFileProvider();
- var fileInfo = fileProvider.AddFile(path, "some content");
- var viewCompiler = GetViewCompiler(fileProvider);
- var changeToken = fileProvider.Watch(path);
-
- // Act 1
- var result1 = await viewCompiler.CompileAsync(path);
-
- // Assert 1
- Assert.NotNull(result1.ViewAttribute);
-
- // Act 2
- fileProvider.DeleteFile(path);
- fileProvider.GetChangeToken(path).HasChanged = true;
- viewCompiler.Compile = _ => throw new Exception("Can't call me");
- var result2 = await viewCompiler.CompileAsync(path);
-
- // Assert 2
- Assert.Same(result1, result2);
- }
-
- [Fact]
- public async Task CompileAsync_InvalidatesCache_IfChangeTokenExpires_WhenWatchingForFileChanges()
- {
- // Arrange
- var path = "/Views/Home/Index.cshtml";
- var fileProvider = new TestFileProvider();
- var fileInfo = fileProvider.AddFile(path, "some content");
- var viewCompiler = GetViewCompiler(fileProvider);
- viewCompiler.AllowRecompilingViewsOnFileChange = true;
-
- // Act 1
- var result1 = await viewCompiler.CompileAsync(path);
-
- // Assert 1
- Assert.NotNull(result1.ViewAttribute);
-
- // Act 2
- fileProvider.DeleteFile(path);
- fileProvider.GetChangeToken(path).HasChanged = true;
- viewCompiler.Compile = _ => throw new Exception("Can't call me");
- var result2 = await viewCompiler.CompileAsync(path);
-
- // Assert 2
- Assert.NotSame(result1, result2);
- Assert.Null(result2.ViewAttribute);
- }
-
- [Fact]
- public async Task CompileAsync_ReturnsNewResultIfFileWasModified()
- {
- // Arrange
- var path = "/Views/Home/Index.cshtml";
- var fileProvider = new TestFileProvider();
- var fileInfo = fileProvider.AddFile(path, "some content");
- var viewCompiler = GetViewCompiler(fileProvider);
- viewCompiler.AllowRecompilingViewsOnFileChange = true;
- var expected2 = new CompiledViewDescriptor();
-
- // Act 1
- var result1 = await viewCompiler.CompileAsync(path);
-
- // Assert 1
- Assert.NotNull(result1.ViewAttribute);
-
- // Act 2
- fileProvider.GetChangeToken(path).HasChanged = true;
- viewCompiler.Compile = _ => expected2;
- var result2 = await viewCompiler.CompileAsync(path);
-
- // Assert 2
- Assert.NotSame(result1, result2);
- Assert.Same(expected2, result2);
- }
-
- [Fact]
- public async Task CompileAsync_ReturnsNewResult_IfAncestorViewImportsWereModified()
- {
- // Arrange
- var path = "/Views/Home/Index.cshtml";
- var fileProvider = new TestFileProvider();
- var fileInfo = fileProvider.AddFile(path, "some content");
- var viewCompiler = GetViewCompiler(fileProvider);
- viewCompiler.AllowRecompilingViewsOnFileChange = true;
- var expected2 = new CompiledViewDescriptor();
-
- // Act 1
- var result1 = await viewCompiler.CompileAsync(path);
-
- // Assert 1
- Assert.NotNull(result1.ViewAttribute);
-
- // Act 2
- fileProvider.GetChangeToken("/Views/_ViewImports.cshtml").HasChanged = true;
- viewCompiler.Compile = _ => expected2;
- var result2 = await viewCompiler.CompileAsync(path);
-
- // Assert 2
- Assert.NotSame(result1, result2);
- Assert.Same(expected2, result2);
- }
-
- [Fact]
- public async Task CompileAsync_ReturnsPrecompiledViews()
- {
- // Arrange
- var path = "/Views/Home/Index.cshtml";
- var fileProvider = new TestFileProvider();
- var fileInfo = fileProvider.AddFile(path, "some content");
- var precompiledView = new CompiledViewDescriptor
+ var compiledView = new CompiledViewDescriptor
{
RelativePath = path,
};
- var viewCompiler = GetViewCompiler(fileProvider, precompiledViews: new[] { precompiledView });
+ var viewCompiler = GetViewCompiler(compiledViews: new[] { compiledView });
// Act
var result = await viewCompiler.CompileAsync(path);
// Assert
- Assert.Same(precompiledView, result);
+ Assert.Same(compiledView, result);
// This view doesn't have checksums so it can't be recompiled.
- Assert.Null(precompiledView.ExpirationTokens);
+ Assert.Null(compiledView.ExpirationTokens);
}
[Theory]
[InlineData("/views/home/index.cshtml")]
[InlineData("/VIEWS/HOME/INDEX.CSHTML")]
[InlineData("/viEws/HoME/inDex.cshtml")]
- public async Task CompileAsync_PerformsCaseInsensitiveLookupsForPrecompiledViews(string lookupPath)
+ public async Task CompileAsync_PerformsCaseInsensitiveLookupsForCompiledViews(string lookupPath)
{
// Arrange
var path = "/Views/Home/Index.cshtml";
- var fileProvider = new TestFileProvider();
- var fileInfo = fileProvider.AddFile(path, "some content");
var precompiledView = new CompiledViewDescriptor
{
RelativePath = path,
};
- var viewCompiler = GetViewCompiler(fileProvider, precompiledViews: new[] { precompiledView });
+ var viewCompiler = GetViewCompiler(compiledViews: new[] { precompiledView });
// Act
var result = await viewCompiler.CompileAsync(lookupPath);
@@ -281,744 +70,37 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
}
[Fact]
- public async Task CompileAsync_PerformsCaseInsensitiveLookupsForPrecompiledViews_WithNonNormalizedPaths()
+ public async Task CompileAsync_PerformsCaseInsensitiveLookupsForCompiledViews_WithNonNormalizedPaths()
{
// Arrange
var path = "/Views/Home/Index.cshtml";
- var fileProvider = new TestFileProvider();
- var fileInfo = fileProvider.AddFile(path, "some content");
- var precompiledView = new CompiledViewDescriptor
+ var compiledView = new CompiledViewDescriptor
{
RelativePath = path,
};
- var viewCompiler = GetViewCompiler(fileProvider, precompiledViews: new[] { precompiledView });
+ var viewCompiler = GetViewCompiler(compiledViews: new[] { compiledView });
// Act
var result = await viewCompiler.CompileAsync("Views\\Home\\Index.cshtml");
// Assert
- Assert.Same(precompiledView, result);
+ Assert.Same(compiledView, result);
}
- [Fact]
- public async Task CompileAsync_PrecompiledViewWithoutChecksumForMainSource_DoesNotSupportRecompilation()
+ private static TestRazorViewCompiler GetViewCompiler(IList compiledViews = null)
{
- // Arrange
- var path = "/Views/Home/Index.cshtml";
+ compiledViews = compiledViews ?? Array.Empty();
- var fileProvider = new TestFileProvider();
- var fileInfo = fileProvider.AddFile(path, "some content");
-
- var precompiledView = new CompiledViewDescriptor
- {
- RelativePath = path,
- Item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", path, new object[]
- {
- new RazorSourceChecksumAttribute("sha1", GetChecksum("some content"), "/Views/Some-Other-View"),
- }),
- };
-
- var viewCompiler = GetViewCompiler(fileProvider, precompiledViews: new[] { precompiledView });
-
- // Act - 1
- var result = await viewCompiler.CompileAsync(path);
-
- // Assert - 1
- Assert.Same(precompiledView.Item, result.Item);
-
- // Act - 2
- fileProvider.Watch(path);
- fileProvider.GetChangeToken(path).HasChanged = true;
- result = await viewCompiler.CompileAsync(path);
-
- // Assert - 2
- Assert.Same(precompiledView.Item, result.Item);
-
- // This view doesn't have checksums so it can't be recompiled.
- Assert.Null(result.ExpirationTokens);
- }
-
- [Fact]
- public async Task CompileAsync_PrecompiledViewWithoutAnyChecksum_DoesNotSupportRecompilation()
- {
- // Arrange
- var path = "/Views/Home/Index.cshtml";
-
- var fileProvider = new TestFileProvider();
- var fileInfo = fileProvider.AddFile(path, "some content");
-
- var precompiledView = new CompiledViewDescriptor
- {
- RelativePath = path,
- Item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", path, new object[] { }),
- };
-
- var viewCompiler = GetViewCompiler(fileProvider, precompiledViews: new[] { precompiledView });
-
- // Act - 1
- var result = await viewCompiler.CompileAsync(path);
-
- // Assert - 1
- Assert.Same(precompiledView, result);
-
- // Act - 2
- fileProvider.Watch(path);
- fileProvider.GetChangeToken(path).HasChanged = true;
- result = await viewCompiler.CompileAsync(path);
-
- // Assert - 2
- Assert.Same(precompiledView, result);
-
- // This view doesn't have checksums so it can't be recompiled.
- Assert.Null(result.ExpirationTokens);
- }
-
- [Fact]
- public async Task CompileAsync_PrecompiledViewWithChecksum_UsesPrecompiledViewWhenChecksumIsMatch()
- {
- // Arrange
- var path = "/Views/Home/Index.cshtml";
-
- var fileProvider = new TestFileProvider();
- var fileInfo = fileProvider.AddFile(path, "some content");
-
- var precompiledView = new CompiledViewDescriptor
- {
- RelativePath = path,
- Item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", path, new object[]
- {
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some content"), path),
- }),
- };
-
- var viewCompiler = GetViewCompiler(fileProvider, precompiledViews: new[] { precompiledView });
- viewCompiler.AllowRecompilingViewsOnFileChange = true;
-
- // Act
- var result = await viewCompiler.CompileAsync(path);
-
- // Assert
- Assert.Same(precompiledView.Item, result.Item);
-
- // This view has checksums so it should also have tokens
- Assert.Collection(
- result.ExpirationTokens,
- token => Assert.Same(fileProvider.GetChangeToken(path), token));
- }
-
- [Fact]
- public async Task CompileAsync_PrecompiledViewWithChecksum_CanRejectWhenChecksumFails()
- {
- // Arrange
- var path = "/Views/Home/Index.cshtml";
-
- var fileProvider = new TestFileProvider();
- var fileInfo = fileProvider.AddFile(path, "some content");
-
- var expected = new CompiledViewDescriptor();
-
- var precompiledView = new CompiledViewDescriptor
- {
- RelativePath = path,
- Item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", path, new object[]
- {
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some other content"), path),
- }),
- };
-
- var viewCompiler = GetViewCompiler(fileProvider, precompiledViews: new[] { precompiledView });
- viewCompiler.Compile = _ => expected;
-
- // Act
- var result = await viewCompiler.CompileAsync(path);
-
- // Assert
- Assert.Same(expected, result);
- }
-
- [Fact]
- public async Task CompileAsync_PrecompiledViewWithChecksum_DoesNotAddExpirationTokens()
- {
- // Arrange
- var path = "/Views/Home/Index.cshtml";
-
- var fileProvider = new TestFileProvider();
- var fileInfo = fileProvider.AddFile(path, "some content");
-
- var expected2 = new CompiledViewDescriptor();
-
- var precompiledView = new CompiledViewDescriptor
- {
- RelativePath = path,
- Item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", path, new object[]
- {
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some content"), path),
- }),
- };
-
- var viewCompiler = GetViewCompiler(fileProvider, precompiledViews: new[] { precompiledView });
-
- // Act
- var result = await viewCompiler.CompileAsync(path);
-
- // Assert
- Assert.Same(precompiledView.Item, result.Item);
- Assert.Empty(result.ExpirationTokens);
- }
-
- [Fact]
- public async Task CompileAsync_PrecompiledViewWithChecksum_CanRecompile()
- {
- // Arrange
- var path = "/Views/Home/Index.cshtml";
-
- var fileProvider = new TestFileProvider();
- var fileInfo = fileProvider.AddFile(path, "some content");
-
- var expected2 = new CompiledViewDescriptor();
-
- var precompiledView = new CompiledViewDescriptor
- {
- RelativePath = path,
- Item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", path, new object[]
- {
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some content"), path),
- }),
- };
-
- var viewCompiler = GetViewCompiler(fileProvider, precompiledViews: new[] { precompiledView });
- viewCompiler.AllowRecompilingViewsOnFileChange = true;
-
- // Act - 1
- var result = await viewCompiler.CompileAsync(path);
-
- // Assert - 1
- Assert.Same(precompiledView.Item, result.Item);
- Assert.NotEmpty(result.ExpirationTokens);
-
- // Act - 2
- fileInfo.Content = "some other content";
- fileProvider.GetChangeToken(path).HasChanged = true;
- viewCompiler.Compile = _ => expected2;
- result = await viewCompiler.CompileAsync(path);
-
- // Assert - 2
- Assert.Same(expected2, result);
- }
-
- [Fact]
- public async Task CompileAsync_PrecompiledViewWithChecksum_DoesNotRecompiledWithoutContentChange()
- {
- // Arrange
- var path = "/Views/Home/Index.cshtml";
-
- var fileProvider = new TestFileProvider();
- var fileInfo = fileProvider.AddFile(path, "some content");
-
- var precompiledView = new CompiledViewDescriptor
- {
- RelativePath = path,
- Item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", path, new object[]
- {
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some content"), path),
- }),
- };
-
- var viewCompiler = GetViewCompiler(fileProvider, precompiledViews: new[] { precompiledView });
- viewCompiler.AllowRecompilingViewsOnFileChange = true;
-
- // Act - 1
- var result = await viewCompiler.CompileAsync(path);
-
- // Assert - 1
- Assert.Same(precompiledView.Item, result.Item);
-
- // Act - 2
- fileProvider.GetChangeToken(path).HasChanged = true;
- result = await viewCompiler.CompileAsync(path);
-
- // Assert - 2
- Assert.Same(precompiledView.Item, result.Item);
- }
-
- [Fact]
- public async Task CompileAsync_PrecompiledViewWithChecksum_CanReusePrecompiledViewIfContentChangesToMatch()
- {
- // Arrange
- var path = "/Views/Home/Index.cshtml";
-
- var fileProvider = new TestFileProvider();
- var fileInfo = fileProvider.AddFile(path, "some other content");
-
- var expected1 = new CompiledViewDescriptor();
-
- var precompiledView = new CompiledViewDescriptor
- {
- RelativePath = path,
- Item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", path, new object[]
- {
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some content"), path),
- }),
- };
-
- var viewCompiler = GetViewCompiler(fileProvider, precompiledViews: new[] { precompiledView });
- viewCompiler.AllowRecompilingViewsOnFileChange = true;
- viewCompiler.Compile = _ => expected1;
-
- // Act - 1
- var result = await viewCompiler.CompileAsync(path);
-
- // Assert - 1
- Assert.Same(expected1, result);
-
- // Act - 2
- fileInfo.Content = "some content";
- fileProvider.GetChangeToken(path).HasChanged = true;
- result = await viewCompiler.CompileAsync(path);
-
- // Assert - 2
- Assert.Same(precompiledView.Item, result.Item);
- }
-
- [Fact]
- public async Task CompileAsync_PrecompiledViewWithChecksum_CanRecompileWhenViewImportChanges()
- {
- // Arrange
- var path = "/Views/Home/Index.cshtml";
- var importPath = "/Views/_ViewImports.cshtml";
-
- var fileProvider = new TestFileProvider();
- var fileInfo = fileProvider.AddFile(path, "some content");
- var importFileInfo = fileProvider.AddFile(importPath, "some import");
-
- var expected2 = new CompiledViewDescriptor();
-
- var precompiledView = new CompiledViewDescriptor
- {
- RelativePath = path,
- Item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", path, new object[]
- {
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some content"), path),
- new RazorSourceChecksumAttribute("SHA1", GetChecksum("some import"), importPath),
- }),
- };
-
- var viewCompiler = GetViewCompiler(fileProvider, precompiledViews: new[] { precompiledView });
- viewCompiler.AllowRecompilingViewsOnFileChange = true;
-
- // Act - 1
- var result = await viewCompiler.CompileAsync(path);
-
- // Assert - 1
- Assert.Same(precompiledView.Item, result.Item);
-
- // Act - 2
- importFileInfo.Content = "some import changed";
- fileProvider.GetChangeToken(importPath).HasChanged = true;
- viewCompiler.Compile = _ => expected2;
- result = await viewCompiler.CompileAsync(path);
-
- // Assert - 2
- Assert.Same(expected2, result);
- }
-
- [Fact]
- public async Task GetOrAdd_AllowsConcurrentCompilationOfMultipleRazorPages()
- {
- // Arrange
- var path1 = "/Views/Home/Index.cshtml";
- var path2 = "/Views/Home/About.cshtml";
- var waitDuration = TimeSpan.FromSeconds(20);
-
- var fileProvider = new TestFileProvider();
- fileProvider.AddFile(path1, "Index content");
- fileProvider.AddFile(path2, "About content");
-
- var resetEvent1 = new AutoResetEvent(initialState: false);
- var resetEvent2 = new ManualResetEvent(initialState: false);
-
- var compilingOne = false;
- var compilingTwo = false;
-
- var result1 = new CompiledViewDescriptor();
- var result2 = new CompiledViewDescriptor();
-
- var compiler = GetViewCompiler(fileProvider);
-
- compiler.Compile = path =>
- {
- if (path == path1)
- {
- compilingOne = true;
-
- // Event 2
- Assert.True(resetEvent1.WaitOne(waitDuration));
-
- // Event 3
- Assert.True(resetEvent2.Set());
-
- // Event 6
- Assert.True(resetEvent1.WaitOne(waitDuration));
-
- Assert.True(compilingTwo);
-
- return result1;
- }
- else if (path == path2)
- {
- compilingTwo = true;
-
- // Event 4
- Assert.True(resetEvent2.WaitOne(waitDuration));
-
- // Event 5
- Assert.True(resetEvent1.Set());
-
- Assert.True(compilingOne);
-
- return result2;
- }
- else
- {
- throw new Exception();
- }
- };
-
- // Act
- var task1 = Task.Run(() => compiler.CompileAsync(path1));
- var task2 = Task.Run(() => compiler.CompileAsync(path2));
-
- // Event 1
- resetEvent1.Set();
-
- await Task.WhenAll(task1, task2);
-
- // Assert
- Assert.True(compilingOne);
- Assert.True(compilingTwo);
- Assert.Same(result1, task1.Result);
- Assert.Same(result2, task2.Result);
- }
-
- [Fact]
- public async Task CompileAsync_DoesNotCreateMultipleCompilationResults_ForConcurrentInvocations()
- {
- // Arrange
- var path = "/Views/Home/Index.cshtml";
- var waitDuration = TimeSpan.FromSeconds(20);
- var fileProvider = new TestFileProvider();
- fileProvider.AddFile(path, "some content");
- var resetEvent1 = new ManualResetEvent(initialState: false);
- var resetEvent2 = new ManualResetEvent(initialState: false);
- var compiler = GetViewCompiler(fileProvider);
-
- compiler.Compile = _ =>
- {
- // Event 2
- resetEvent1.WaitOne(waitDuration);
-
- // Event 3
- resetEvent2.Set();
- return new CompiledViewDescriptor();
- };
-
- // Act
- var task1 = Task.Run(() => compiler.CompileAsync(path));
- var task2 = Task.Run(() =>
- {
- // Event 4
- Assert.True(resetEvent2.WaitOne(waitDuration));
- return compiler.CompileAsync(path);
- });
-
- // Event 1
- resetEvent1.Set();
- await Task.WhenAll(task1, task2);
-
- // Assert
- var result1 = task1.Result;
- var result2 = task2.Result;
- Assert.Same(result1, result2);
- }
-
- [Fact]
- public async Task GetOrAdd_CachesCompilationExceptions()
- {
- // Arrange
- var path = "/Views/Home/Index.cshtml";
- var fileProvider = new TestFileProvider();
- fileProvider.AddFile(path, "some content");
- var exception = new InvalidTimeZoneException();
- var compiler = GetViewCompiler(fileProvider);
- compiler.Compile = _ => throw exception;
-
- // Act and Assert - 1
- var actual = await Assert.ThrowsAsync(
- () => compiler.CompileAsync(path));
- Assert.Same(exception, actual);
-
- // Act and Assert - 2
- compiler.Compile = _ => throw new Exception("Shouldn't be called");
-
- actual = await Assert.ThrowsAsync(
- () => compiler.CompileAsync(path));
- Assert.Same(exception, actual);
- }
-
- [Fact]
- public void Compile_SucceedsForCSharp7()
- {
- // Arrange
- var content = @"
-public class MyTestType
-{
- private string _name;
-
- public string Name
- {
- get => _name;
- set => _name = value ?? throw new System.ArgumentNullException(nameof(value));
- }
-}";
- var compiler = GetViewCompiler(new TestFileProvider());
- var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.Create("razor-content", "filename"));
-
- // Act
- var result = compiler.CompileAndEmit(codeDocument, content);
-
- // Assert
- var exportedType = Assert.Single(result.ExportedTypes);
- Assert.Equal("MyTestType", exportedType.Name);
- }
-
- [Fact]
- public void Compile_ReturnsCompilationFailureWithPathsFromLinePragmas()
- {
- // Arrange
- var viewPath = "some-relative-path";
- var fileContent = "test file content";
- var content = $@"
-#line 1 ""{viewPath}""
-this should fail";
-
- var compiler = GetViewCompiler(new TestFileProvider());
- var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.Create(fileContent, viewPath));
-
- // Act & Assert
- var ex = Assert.Throws(() => compiler.CompileAndEmit(codeDocument, content));
-
- var compilationFailure = Assert.Single(ex.CompilationFailures);
- Assert.Equal(viewPath, compilationFailure.SourceFilePath);
- Assert.Equal(fileContent, compilationFailure.SourceFileContent);
- }
-
- [Fact]
- public void Compile_ReturnsGeneratedCodePath_IfLinePragmaIsNotAvailable()
- {
- // Arrange
- var viewPath = "some-relative-path";
- var fileContent = "file content";
- var content = "this should fail";
-
- var compiler = GetViewCompiler(new TestFileProvider());
- var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.Create(fileContent, viewPath));
-
- // Act & Assert
- var ex = Assert.Throws(() => compiler.CompileAndEmit(codeDocument, content));
-
- var compilationFailure = Assert.Single(ex.CompilationFailures);
- Assert.Equal("Generated Code", compilationFailure.SourceFilePath);
- Assert.Equal(content, compilationFailure.SourceFileContent);
- }
-
- [Fact]
- public void Compile_InvokesCallback()
- {
- // Arrange
- var content = "public class MyTestType {}";
- var callbackInvoked = false;
- var compiler = GetViewCompiler(
- new TestFileProvider(),
- context =>
- {
- callbackInvoked = true;
- });
- var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.Create("some-content", "some-path"));
-
- // Act
- var result = compiler.CompileAndEmit(codeDocument, content);
-
- // Assert
- Assert.True(callbackInvoked);
- }
-
- [Fact]
- public void Compile_SucceedsIfReferencesAreAddedInCallback()
- {
- // Arrange
- Action compilationCallback = context =>
- {
- var assemblyLocation = typeof(object).Assembly.Location;
-
- context.Compilation = context
- .Compilation
- .AddReferences(MetadataReference.CreateFromFile(assemblyLocation));
- };
-
- var applicationPartManager = new ApplicationPartManager();
- var referenceManager = new DefaultRazorReferenceManager(
- applicationPartManager,
- Options.Create(new RazorViewEngineOptions()));
- var compiler = GetViewCompiler(
- compilationCallback: compilationCallback,
- referenceManager: referenceManager);
-
- var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.Create("Hello world", "some-relative-path.cshtml"));
-
- // Act
- var result = compiler.CompileAndEmit(codeDocument, "public class Test {}");
-
- // Assert
- Assert.NotNull(result);
- }
-
- [Fact]
- public void CompileAndEmit_DoesNotThrowIfDebugTypeIsEmbedded()
- {
- // Arrange
- var referenceManager = CreateReferenceManager(Options.Create(new RazorViewEngineOptions()));
- var csharpCompiler = new TestCSharpCompiler(referenceManager, Mock.Of())
- {
- EmitOptionsSettable = new EmitOptions(debugInformationFormat: DebugInformationFormat.Embedded),
- };
-
- var compiler = GetViewCompiler(csharpCompiler: csharpCompiler);
- var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.Create("Hello world", "some-relative-path.cshtml"));
-
- // Act
- var result = compiler.CompileAndEmit(codeDocument, "public class Test{}");
-
- // Assert
- Assert.NotNull(result);
- }
-
- [Fact]
- public void CompileAndEmit_WorksIfEmitPdbIsNotSet()
- {
- // Arrange
- var referenceManager = CreateReferenceManager(Options.Create(new RazorViewEngineOptions()));
- var csharpCompiler = new TestCSharpCompiler(referenceManager, Mock.Of())
- {
- EmitPdbSettable = false,
- };
-
- var compiler = GetViewCompiler(csharpCompiler: csharpCompiler);
- var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.Create("Hello world", "some-relative-path.cshtml"));
-
- // Act
- var result = compiler.CompileAndEmit(codeDocument, "public class Test{}");
-
- // Assert
- Assert.NotNull(result);
- }
-
- private static TestRazorViewCompiler GetViewCompiler(
- TestFileProvider fileProvider = null,
- Action compilationCallback = null,
-#pragma warning disable CS0618 // Type or member is obsolete
- RazorReferenceManager referenceManager = null,
-#pragma warning restore CS0618 // Type or member is obsolete
- IList precompiledViews = null,
- CSharpCompiler csharpCompiler = null)
- {
- fileProvider = fileProvider ?? new TestFileProvider();
- var accessor = Mock.Of(a => a.FileProvider == fileProvider);
-
- compilationCallback = compilationCallback ?? (_ => { });
- var options = Options.Create(new RazorViewEngineOptions());
- if (referenceManager == null)
- {
- referenceManager = CreateReferenceManager(options);
- }
-
- precompiledViews = precompiledViews ?? Array.Empty();
-
- var hostingEnvironment = Mock.Of(e => e.ContentRootPath == "BasePath");
- var fileSystem = new FileProviderRazorProjectFileSystem(accessor, hostingEnvironment);
- var projectEngine = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem, builder =>
- {
- RazorExtensions.Register(builder);
- });
-
- csharpCompiler = csharpCompiler ?? new CSharpCompiler(referenceManager, hostingEnvironment);
-
- var viewCompiler = new TestRazorViewCompiler(
- fileProvider,
- projectEngine,
- csharpCompiler,
- compilationCallback,
- precompiledViews);
+ var viewCompiler = new TestRazorViewCompiler(compiledViews);
return viewCompiler;
}
-#pragma warning disable CS0618 // Type or member is obsolete
- private static RazorReferenceManager CreateReferenceManager(IOptions options)
- {
- var applicationPartManager = new ApplicationPartManager();
- var assembly = typeof(RazorViewCompilerTest).Assembly;
- applicationPartManager.ApplicationParts.Add(new AssemblyPart(assembly));
- applicationPartManager.FeatureProviders.Add(new MetadataReferenceFeatureProvider());
-
- return new DefaultRazorReferenceManager(applicationPartManager, options);
- }
-#pragma warning restore CS0618 // Type or member is obsolete
-
private class TestRazorViewCompiler : RazorViewCompiler
{
- public TestRazorViewCompiler(
- TestFileProvider fileProvider,
- RazorProjectEngine projectEngine,
- CSharpCompiler csharpCompiler,
- Action compilationCallback,
- IList precompiledViews,
- Func compile = null) :
- base(fileProvider, projectEngine, csharpCompiler, compilationCallback, precompiledViews, new MemoryCache(new MemoryCacheOptions()), NullLogger.Instance)
- {
- Compile = compile;
- if (Compile == null)
- {
- Compile = path => new CompiledViewDescriptor
- {
- RelativePath = path,
- ViewAttribute = new RazorViewAttribute(path, typeof(object)),
- };
- }
- }
-
- public Func Compile { get; set; }
-
- protected override CompiledViewDescriptor CompileAndEmit(string relativePath)
- {
- return Compile(relativePath);
- }
- }
-
- private class TestCSharpCompiler : CSharpCompiler
- {
-#pragma warning disable CS0618 // Type or member is obsolete
- public TestCSharpCompiler(RazorReferenceManager manager, IHostingEnvironment hostingEnvironment)
-#pragma warning restore CS0618 // Type or member is obsolete
- : base(manager, hostingEnvironment)
+ public TestRazorViewCompiler(IList compiledViews) :
+ base(compiledViews, NullLogger.Instance)
{
}
-
- public EmitOptions EmitOptionsSettable { get; set; }
-
- public bool EmitPdbSettable { get; set; }
-
- public override EmitOptions EmitOptions => EmitOptionsSettable;
-
- public override bool EmitPdb => EmitPdbSettable;
}
}
}
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/DefaultRazorViewEngineFileProviderAccessorTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/DefaultRazorViewEngineFileProviderAccessorTest.cs
deleted file mode 100644
index d69853f2b..000000000
--- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/DefaultRazorViewEngineFileProviderAccessorTest.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-// 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 Microsoft.Extensions.FileProviders;
-using Microsoft.Extensions.Options;
-using Moq;
-using Xunit;
-
-namespace Microsoft.AspNetCore.Mvc.Razor
-{
- public class DefaultRazorViewEngineFileProviderAccessorTest
- {
- [Fact]
- public void FileProvider_ReturnsInstance_IfExactlyOneFileProviderIsRegistered()
- {
- // Arrange
- var fileProvider = new TestFileProvider();
- var options = new RazorViewEngineOptions();
- options.FileProviders.Add(fileProvider);
- var optionsAccessor = new Mock>();
- optionsAccessor.SetupGet(o => o.Value).Returns(options);
- var fileProviderAccessor = new DefaultRazorViewEngineFileProviderAccessor(optionsAccessor.Object);
-
- // Act
- var actual = fileProviderAccessor.FileProvider;
-
- // Assert
- Assert.Same(fileProvider, actual);
- }
-
- [Fact]
- public void FileProvider_ReturnsNullFileProvider_IfNoInstancesAreRegistered()
- {
- // Arrange
- var options = new RazorViewEngineOptions();
- var optionsAccessor = new Mock>();
- optionsAccessor.SetupGet(o => o.Value).Returns(options);
- var fileProviderAccessor = new DefaultRazorViewEngineFileProviderAccessor(optionsAccessor.Object);
-
- // Act
- var actual = fileProviderAccessor.FileProvider;
-
- // Assert
- Assert.IsType(actual);
- }
-
- [Fact]
- public void FileProvider_ReturnsCompositeFileProvider_IfMoreThanOneInstanceIsRegistered()
- {
- // Arrange
- var options = new RazorViewEngineOptions();
- options.FileProviders.Add(new TestFileProvider());
- options.FileProviders.Add(new TestFileProvider());
- var optionsAccessor = new Mock>();
- optionsAccessor.SetupGet(o => o.Value).Returns(options);
- var fileProviderAccessor = new DefaultRazorViewEngineFileProviderAccessor(optionsAccessor.Object);
-
- // Act
- var actual = fileProviderAccessor.FileProvider;
-
- // Assert
- Assert.IsType(actual);
- }
- }
-}
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/DependencyInjection/MvcRazorMvcCoreBuilderExtensionsTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/DependencyInjection/MvcRazorMvcCoreBuilderExtensionsTest.cs
index bf5e47176..ad46856f3 100644
--- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/DependencyInjection/MvcRazorMvcCoreBuilderExtensionsTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/DependencyInjection/MvcRazorMvcCoreBuilderExtensionsTest.cs
@@ -53,63 +53,6 @@ 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
-#pragma warning disable CS0618 // Type or member is obsolete
- Assert.Single(builder.PartManager.FeatureProviders.OfType());
-#pragma warning restore CS0618 // Type or member is obsolete
- }
-
- [Fact]
- public void AddRazorViewEngine_DoesNotAddMultipleMetadataReferenceFeatureProvider_OnMultipleInvocations()
- {
- // Arrange
- var services = new ServiceCollection();
- var builder = services.AddMvcCore();
-
- // Act - 1
- builder.AddRazorViewEngine();
-
- // Act - 2
- builder.AddRazorViewEngine();
-
- // Assert
-#pragma warning disable CS0618 // Type or member is obsolete
- Assert.Single(builder.PartManager.FeatureProviders.OfType());
-#pragma warning restore CS0618 // Type or member is obsolete
- }
-
- [Fact]
- public void AddRazorViewEngine_DoesNotReplaceExistingMetadataReferenceFeatureProvider()
- {
- // Arrange
- var services = new ServiceCollection();
- var builder = services.AddMvcCore();
-#pragma warning disable CS0618 // Type or member is obsolete
- var metadataReferenceFeatureProvider = new MetadataReferenceFeatureProvider();
-#pragma warning restore CS0618 // Type or member is obsolete
- builder.PartManager.FeatureProviders.Add(metadataReferenceFeatureProvider);
-
- // Act
- builder.AddRazorViewEngine();
-
- // Assert
- var actual = Assert.Single(
-#pragma warning disable CS0618 // Type or member is obsolete
- collection: builder.PartManager.FeatureProviders.OfType());
-#pragma warning restore CS0618 // Type or member is obsolete
- Assert.Same(metadataReferenceFeatureProvider, actual);
- }
-
[Fact]
public void AddTagHelpersAsServices_ReplacesTagHelperActivatorAndTagHelperTypeResolver()
{
diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/DependencyInjection/RazorViewEngineOptionsSetupTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/DependencyInjection/RazorViewEngineOptionsSetupTest.cs
deleted file mode 100644
index 79d9b334d..000000000
--- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/DependencyInjection/RazorViewEngineOptionsSetupTest.cs
+++ /dev/null
@@ -1,161 +0,0 @@
-// 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 Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.AspNetCore.Mvc.Infrastructure;
-using Microsoft.AspNetCore.Mvc.Razor;
-using Microsoft.Extensions.FileProviders;
-using Microsoft.Extensions.Logging.Abstractions;
-using Microsoft.Extensions.Options;
-using Moq;
-using Xunit;
-
-namespace Microsoft.Extensions.DependencyInjection
-{
- public class RazorViewEngineOptionsSetupTest
- {
- [Fact]
- public void RazorViewEngineOptionsSetup_SetsUpFileProvider()
- {
- // Arrange
- var options = new RazorViewEngineOptions();
- var expected = Mock.Of();
- var hostingEnv = new Mock();
- hostingEnv.SetupGet(e => e.ContentRootFileProvider)
- .Returns(expected);
-
- var optionsSetup = GetSetup(hostingEnvironment: hostingEnv.Object);
-
- // Act
- optionsSetup.Configure(options);
-
- // Assert
- var fileProvider = Assert.Single(options.FileProviders);
- Assert.Same(expected, fileProvider);
- }
-
- [Fact]
- public void PostConfigure_SetsAllowRecompilingViewsOnFileChange_For21()
- {
- // Arrange
- var options = new RazorViewEngineOptions();
- var optionsSetup = GetSetup(CompatibilityVersion.Version_2_1);
-
- // Act
- optionsSetup.Configure(options);
- optionsSetup.PostConfigure(string.Empty, options);
-
- // Assert
- Assert.True(options.AllowRecompilingViewsOnFileChange);
- }
-
- [Theory]
- [InlineData(CompatibilityVersion.Version_2_2)]
- [InlineData(CompatibilityVersion.Latest)]
- public void PostConfigure_SetsAllowRecompilingViewsOnFileChange_InDevelopmentMode(CompatibilityVersion compatibilityVersion)
- {
- // Arrange
- var options = new RazorViewEngineOptions();
- var hostingEnv = Mock.Of(env => env.EnvironmentName == EnvironmentName.Development);
- var optionsSetup = GetSetup(compatibilityVersion, hostingEnv);
-
- // Act
- optionsSetup.Configure(options);
- optionsSetup.PostConfigure(string.Empty, options);
-
- // Assert
- Assert.True(options.AllowRecompilingViewsOnFileChange);
- }
-
- [Theory]
- [InlineData(CompatibilityVersion.Version_2_2)]
- [InlineData(CompatibilityVersion.Latest)]
- public void PostConfigure_DoesNotSetAllowRecompilingViewsOnFileChange_WhenNotInDevelopment(CompatibilityVersion compatibilityVersion)
- {
- // Arrange
- var options = new RazorViewEngineOptions();
- var hostingEnv = Mock.Of(env => env.EnvironmentName == EnvironmentName.Staging);
- var optionsSetup = GetSetup(compatibilityVersion, hostingEnv);
-
- // Act
- optionsSetup.Configure(options);
- optionsSetup.PostConfigure(string.Empty, options);
-
- // Assert
- Assert.False(options.AllowRecompilingViewsOnFileChange);
- }
-
- [Fact]
- public void RazorViewEngineOptionsSetup_DoesNotOverwriteAllowRecompilingViewsOnFileChange_In21CompatMode()
- {
- // Arrange
- var hostingEnv = Mock.Of(env => env.EnvironmentName == EnvironmentName.Staging);
- var compatibilityVersion = new MvcCompatibilityOptions { CompatibilityVersion = CompatibilityVersion.Version_2_1 };
- var optionsSetup = GetSetup(CompatibilityVersion.Version_2_1, hostingEnv);
- var serviceProvider = new ServiceCollection()
- .AddOptions()
- .AddSingleton>(optionsSetup)
- .Configure(o => o.AllowRecompilingViewsOnFileChange = false)
- .BuildServiceProvider();
-
- // Act
- var options = serviceProvider.GetRequiredService>();
-
- // Assert
- Assert.False(options.Value.AllowRecompilingViewsOnFileChange);
- }
-
- [Fact]
- public void RazorViewEngineOptionsSetup_ConfiguresAllowRecompilingViewsOnFileChange()
- {
- // Arrange
- var hostingEnv = Mock.Of(env => env.EnvironmentName == EnvironmentName.Production);
- var compatibilityVersion = new MvcCompatibilityOptions { CompatibilityVersion = CompatibilityVersion.Version_2_2 };
- var optionsSetup = GetSetup(CompatibilityVersion.Version_2_2, hostingEnv);
- var serviceProvider = new ServiceCollection()
- .AddOptions()
- .AddSingleton>(optionsSetup)
- .BuildServiceProvider();
-
- // Act
- var options = serviceProvider.GetRequiredService>();
-
- // Assert
- Assert.False(options.Value.AllowRecompilingViewsOnFileChange);
- }
-
- [Fact]
- public void RazorViewEngineOptionsSetup_DoesNotOverwriteAllowRecompilingViewsOnFileChange()
- {
- // Arrange
- var hostingEnv = Mock.Of(env => env.EnvironmentName == EnvironmentName.Production);
- var optionsSetup = GetSetup(CompatibilityVersion.Version_2_2, hostingEnv);
- var serviceProvider = new ServiceCollection()
- .AddOptions()
- .AddSingleton>(optionsSetup)
- .Configure(o => o.AllowRecompilingViewsOnFileChange = true)
- .BuildServiceProvider();
-
- // Act
- var options = serviceProvider.GetRequiredService