This commit is contained in:
Pranav K 2016-01-12 12:37:08 -08:00
Родитель d0046cafe9
Коммит 32d15186a0
44 изменённых файлов: 20 добавлений и 1708 удалений

Просмотреть файл

@ -99,7 +99,7 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "LocalizationSample.Web", "s
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ActionConstraintSample.Web", "samples\ActionConstraintSample.Web\ActionConstraintSample.Web.xproj", "{EE0BD773-4D47-4AA8-8472-5A938A3953BA}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MvcSubAreaSample.Web", "samples\MvcSubAreaSample.Web\MvcSubAreaSample.Web.xproj", "{E1D45BAF-3967-4D81-9217-22AA54941BF5}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MvcSubAreaSample.Web", "samples\MvcSubAreaSample.Web\MvcSubAreaSample.Web.xproj", "{45F6B3B6-D114-4D77-84D6-561B3957F341}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -593,18 +593,18 @@ Global
{EE0BD773-4D47-4AA8-8472-5A938A3953BA}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{EE0BD773-4D47-4AA8-8472-5A938A3953BA}.Release|x86.ActiveCfg = Release|Any CPU
{EE0BD773-4D47-4AA8-8472-5A938A3953BA}.Release|x86.Build.0 = Release|Any CPU
{E1D45BAF-3967-4D81-9217-22AA54941BF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E1D45BAF-3967-4D81-9217-22AA54941BF5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E1D45BAF-3967-4D81-9217-22AA54941BF5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{E1D45BAF-3967-4D81-9217-22AA54941BF5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{E1D45BAF-3967-4D81-9217-22AA54941BF5}.Debug|x86.ActiveCfg = Debug|Any CPU
{E1D45BAF-3967-4D81-9217-22AA54941BF5}.Debug|x86.Build.0 = Debug|Any CPU
{E1D45BAF-3967-4D81-9217-22AA54941BF5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E1D45BAF-3967-4D81-9217-22AA54941BF5}.Release|Any CPU.Build.0 = Release|Any CPU
{E1D45BAF-3967-4D81-9217-22AA54941BF5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{E1D45BAF-3967-4D81-9217-22AA54941BF5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{E1D45BAF-3967-4D81-9217-22AA54941BF5}.Release|x86.ActiveCfg = Release|Any CPU
{E1D45BAF-3967-4D81-9217-22AA54941BF5}.Release|x86.Build.0 = Release|Any CPU
{45F6B3B6-D114-4D77-84D6-561B3957F341}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{45F6B3B6-D114-4D77-84D6-561B3957F341}.Debug|Any CPU.Build.0 = Debug|Any CPU
{45F6B3B6-D114-4D77-84D6-561B3957F341}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{45F6B3B6-D114-4D77-84D6-561B3957F341}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{45F6B3B6-D114-4D77-84D6-561B3957F341}.Debug|x86.ActiveCfg = Debug|Any CPU
{45F6B3B6-D114-4D77-84D6-561B3957F341}.Debug|x86.Build.0 = Debug|Any CPU
{45F6B3B6-D114-4D77-84D6-561B3957F341}.Release|Any CPU.ActiveCfg = Release|Any CPU
{45F6B3B6-D114-4D77-84D6-561B3957F341}.Release|Any CPU.Build.0 = Release|Any CPU
{45F6B3B6-D114-4D77-84D6-561B3957F341}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{45F6B3B6-D114-4D77-84D6-561B3957F341}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{45F6B3B6-D114-4D77-84D6-561B3957F341}.Release|x86.ActiveCfg = Release|Any CPU
{45F6B3B6-D114-4D77-84D6-561B3957F341}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -652,6 +652,6 @@ Global
{DAB1252D-577C-4912-98BE-1A812BF83F86} = {DAAE4C74-D06F-4874-A166-33305D2643CE}
{FCFE6024-2720-49B4-8257-9DBC6114F0F1} = {DAAE4C74-D06F-4874-A166-33305D2643CE}
{EE0BD773-4D47-4AA8-8472-5A938A3953BA} = {DAAE4C74-D06F-4874-A166-33305D2643CE}
{E1D45BAF-3967-4D81-9217-22AA54941BF5} = {DAAE4C74-D06F-4874-A166-33305D2643CE}
{45F6B3B6-D114-4D77-84D6-561B3957F341} = {DAAE4C74-D06F-4874-A166-33305D2643CE}
EndGlobalSection
EndGlobal

13
Mvc.sln
Просмотреть файл

@ -70,8 +70,6 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.TagHel
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.TagHelpers.Test", "test\Microsoft.AspNet.Mvc.TagHelpers.Test\Microsoft.AspNet.Mvc.TagHelpers.Test.xproj", "{860119ED-3DB1-424D-8D0A-30132A8A7D96}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PrecompilationWebSite", "test\WebSites\PrecompilationWebSite\PrecompilationWebSite.xproj", "{59E1BE90-92C1-4D35-ADCC-B69F49077C81}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "HtmlGenerationWebSite", "test\WebSites\HtmlGenerationWebSite\HtmlGenerationWebSite.xproj", "{920F8A0E-6F7D-4BBE-84FF-840B89099BE6}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ErrorPageMiddlewareWebSite", "test\WebSites\ErrorPageMiddlewareWebSite\ErrorPageMiddlewareWebSite.xproj", "{AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}"
@ -426,16 +424,6 @@ Global
{860119ED-3DB1-424D-8D0A-30132A8A7D96}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{860119ED-3DB1-424D-8D0A-30132A8A7D96}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{860119ED-3DB1-424D-8D0A-30132A8A7D96}.Release|x86.ActiveCfg = Release|Any CPU
{59E1BE90-92C1-4D35-ADCC-B69F49077C81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{59E1BE90-92C1-4D35-ADCC-B69F49077C81}.Debug|Any CPU.Build.0 = Debug|Any CPU
{59E1BE90-92C1-4D35-ADCC-B69F49077C81}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{59E1BE90-92C1-4D35-ADCC-B69F49077C81}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{59E1BE90-92C1-4D35-ADCC-B69F49077C81}.Debug|x86.ActiveCfg = Debug|Any CPU
{59E1BE90-92C1-4D35-ADCC-B69F49077C81}.Release|Any CPU.ActiveCfg = Release|Any CPU
{59E1BE90-92C1-4D35-ADCC-B69F49077C81}.Release|Any CPU.Build.0 = Release|Any CPU
{59E1BE90-92C1-4D35-ADCC-B69F49077C81}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{59E1BE90-92C1-4D35-ADCC-B69F49077C81}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{59E1BE90-92C1-4D35-ADCC-B69F49077C81}.Release|x86.ActiveCfg = Release|Any CPU
{920F8A0E-6F7D-4BBE-84FF-840B89099BE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{920F8A0E-6F7D-4BBE-84FF-840B89099BE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{920F8A0E-6F7D-4BBE-84FF-840B89099BE6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@ -912,7 +900,6 @@ Global
{2223120F-D675-40DA-8CD8-11DC14A0B2C7} = {DAAE4C74-D06F-4874-A166-33305D2643CE}
{B2347320-308E-4D2B-AEC8-005DFA68B0C9} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
{860119ED-3DB1-424D-8D0A-30132A8A7D96} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{59E1BE90-92C1-4D35-ADCC-B69F49077C81} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{920F8A0E-6F7D-4BBE-84FF-840B89099BE6} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{AD545A5B-2BA5-4314-88AC-FC2ACF2CC718} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{C3123A70-41C4-4122-AD1C-D35DF8958DD7} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}

Просмотреть файл

@ -1,18 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="14.0.24720" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.24720</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>59e1be90-92c1-4d35-adcc-b69f49077c81</ProjectGuid>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
<ProjectGuid>45F6B3B6-D114-4D77-84D6-561B3957F341</ProjectGuid>
<RootNamespace>MvcSubAreaSample.Web</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<DevelopmentServerPort>40958</DevelopmentServerPort>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

Просмотреть файл

@ -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 System;
using Microsoft.AspNet.Mvc.Razor.Precompilation;
namespace TagHelperSample.Web
{
public class TagHelpersRazorPreCompilation : RazorPreCompileModule
{
}
}

Просмотреть файл

@ -1,109 +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 System.Threading;
using Microsoft.AspNet.FileProviders;
using Microsoft.AspNet.Mvc.Razor.Precompilation;
using Microsoft.Extensions.PlatformAbstractions;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNet.Mvc.Razor.Compilation
{
/// <summary>
/// An <see cref="ICompilerCacheProvider"/> that provides a <see cref="CompilerCache"/> instance
/// populated with precompiled views.
/// </summary>
public class PrecompiledViewsCompilerCacheProvider : ICompilerCacheProvider
{
private static readonly Assembly RazorAssembly = typeof(DefaultCompilerCacheProvider).GetTypeInfo().Assembly;
private static readonly Type RazorFileInfoCollectionType = typeof(RazorFileInfoCollection);
private readonly Func<ICompilerCache> _createCache;
private readonly IAssemblyLoadContextAccessor _loadContextAccessor;
private readonly IFileProvider _fileProvider;
private readonly Assembly[] _assemblies;
private object _cacheLock = new object();
private bool _cacheInitialized;
private ICompilerCache _compilerCache;
/// <summary>
/// Initializes a new instance of <see cref="DefaultCompilerCacheProvider"/>.
/// </summary>
/// <param name="loadContextAccessor">The <see cref="IAssemblyLoadContextAccessor"/>.</param>
/// <param name="fileProviderAccessor">The <see cref="IRazorViewEngineFileProviderAccessor"/>.</param>
/// <param name="assemblies"><see cref="Assembly"/> instances to scan for precompiled views.</param>
public PrecompiledViewsCompilerCacheProvider(
IAssemblyLoadContextAccessor loadContextAccessor,
IRazorViewEngineFileProviderAccessor fileProviderAccessor,
IEnumerable<Assembly> assemblies)
{
_loadContextAccessor = loadContextAccessor;
_fileProvider = fileProviderAccessor.FileProvider;
_createCache = CreateCache;
_assemblies = assemblies.ToArray();
}
/// <inheritdoc />
public ICompilerCache Cache
{
get
{
return LazyInitializer.EnsureInitialized(
ref _compilerCache,
ref _cacheInitialized,
ref _cacheLock,
_createCache);
}
}
private ICompilerCache CreateCache()
{
var razorFileInfoCollections = GetFileInfoCollections(_assemblies);
var loadContext = _loadContextAccessor.GetLoadContext(RazorAssembly);
var precompiledViews = GetPrecompiledViews(razorFileInfoCollections, loadContext);
return new CompilerCache(_fileProvider, precompiledViews);
}
// Internal for unit testing
internal static Dictionary<string, Type> GetPrecompiledViews(
IEnumerable<RazorFileInfoCollection> razorFileInfoCollections,
IAssemblyLoadContext loadContext)
{
var precompiledViews = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
foreach (var viewCollection in razorFileInfoCollections)
{
var containingAssembly = viewCollection.LoadAssembly(loadContext);
foreach (var fileInfo in viewCollection.FileInfos)
{
var viewType = containingAssembly.GetType(fileInfo.FullTypeName);
precompiledViews[fileInfo.RelativePath] = viewType;
}
}
return precompiledViews;
}
private static IEnumerable<RazorFileInfoCollection> GetFileInfoCollections(IEnumerable<Assembly> assemblies)
{
return assemblies
.SelectMany(assembly => assembly.ExportedTypes)
.Where(IsValidRazorFileInfoCollection)
.Select(Activator.CreateInstance)
.Cast<RazorFileInfoCollection>();
}
internal static bool IsValidRazorFileInfoCollection(Type type)
{
return
RazorFileInfoCollectionType.IsAssignableFrom(type) &&
!type.GetTypeInfo().IsAbstract &&
!type.GetTypeInfo().ContainsGenericParameters;
}
}
}

Просмотреть файл

@ -73,28 +73,5 @@ namespace Microsoft.Extensions.DependencyInjection
return builder;
}
public static IMvcBuilder AddPrecompiledRazorViews(
this IMvcBuilder builder,
params Assembly[] assemblies)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (assemblies == null)
{
throw new ArgumentNullException(nameof(assemblies));
}
builder.Services.Replace(
ServiceDescriptor.Singleton<ICompilerCacheProvider>(serviceProvider =>
ActivatorUtilities.CreateInstance<PrecompiledViewsCompilerCacheProvider>(
serviceProvider,
assemblies.AsEnumerable())));
return builder;
}
}
}

Просмотреть файл

@ -58,31 +58,6 @@ namespace Microsoft.Extensions.DependencyInjection
return builder;
}
public static IMvcCoreBuilder AddPrecompiledRazorViews(
this IMvcCoreBuilder builder,
params Assembly[] assemblies)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (assemblies == null)
{
throw new ArgumentNullException(nameof(assemblies));
}
AddRazorViewEngine(builder);
builder.Services.Replace(
ServiceDescriptor.Singleton<ICompilerCacheProvider>(serviceProvider =>
ActivatorUtilities.CreateInstance<PrecompiledViewsCompilerCacheProvider>(
serviceProvider,
assemblies.AsEnumerable())));
return builder;
}
/// <summary>
/// Adds an initialization callback for a given <typeparamref name="TTagHelper"/>.
/// </summary>

Просмотреть файл

@ -1,76 +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.CompilerServices;
using System.Text;
using Microsoft.AspNet.Mvc.Razor.Precompilation;
using Microsoft.Extensions.PlatformAbstractions;
namespace Microsoft.AspNet.Mvc.Razor.Internal
{
/// <summary>
/// Utility type to code generate <see cref="RazorFileInfoCollection"/> types.
/// </summary>
public static class RazorFileInfoCollectionGenerator
{
/// <summary>
/// Generates CSharp code for the specified <paramref name="fileInfoCollection"/>.
/// </summary>
/// <param name="fileInfoCollection">The <see cref="RazorFileInfoCollection"/>.</param>
/// <returns></returns>
public static string GenerateCode(RazorFileInfoCollection fileInfoCollection)
{
if (fileInfoCollection == null)
{
throw new ArgumentNullException(nameof(fileInfoCollection));
}
var builder = new StringBuilder();
builder.Append(
$@"namespace __ASP_ASSEMBLY
{{
[{typeof(CompilerGeneratedAttribute).FullName}]
public class __PreGeneratedViewCollection : {typeof(RazorFileInfoCollection).FullName}
{{
public __PreGeneratedViewCollection()
{{
{nameof(RazorFileInfoCollection.AssemblyResourceName)} = @""{fileInfoCollection.AssemblyResourceName}"";
{nameof(RazorFileInfoCollection.SymbolsResourceName)} = @""{fileInfoCollection.SymbolsResourceName}"";
FileInfos = new System.Collections.Generic.List<{typeof(RazorFileInfo).FullName}>
{{");
foreach (var fileInfo in fileInfoCollection.FileInfos)
{
builder.Append(
$@"
new {typeof(RazorFileInfo).FullName}
{{
{nameof(RazorFileInfo.FullTypeName)} = @""{fileInfo.FullTypeName}"",
{nameof(RazorFileInfo.RelativePath)} = @""{fileInfo.RelativePath}""
}},");
}
builder.Append(
$@"
}};
}}
private static {typeof(System.Reflection.Assembly).FullName} _loadedAssembly;
public override {typeof(System.Reflection.Assembly).FullName} LoadAssembly(
{typeof(IAssemblyLoadContext).FullName} loadContext)
{{
if (_loadedAssembly == null)
{{
_loadedAssembly = base.LoadAssembly(loadContext);
}}
return _loadedAssembly;
}}
}}
}}");
return builder.ToString();
}
}
}

Просмотреть файл

@ -1,54 +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.AspNet.Razor.CodeGenerators;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.AspNet.Mvc.Razor.Precompilation
{
public static class GeneratorResultExtensions
{
public static string GetMainClassName(
this GeneratorResults results,
IMvcRazorHost host,
SyntaxTree syntaxTree)
{
if (results == null)
{
throw new ArgumentNullException(nameof(results));
}
if (host == null)
{
throw new ArgumentNullException(nameof(host));
}
if (syntaxTree == null)
{
throw new ArgumentNullException(nameof(syntaxTree));
}
// The mainClass name should return directly from the generator results.
var classes = syntaxTree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>();
var mainClass = classes.FirstOrDefault(c =>
c.Identifier.ValueText.StartsWith(host.MainClassNamePrefix, StringComparison.Ordinal));
if (mainClass != null)
{
var typeName = mainClass.Identifier.ValueText;
if (!string.IsNullOrEmpty(host.DefaultNamespace))
{
typeName = host.DefaultNamespace + "." + typeName;
}
return typeName;
}
return null;
}
}
}

Просмотреть файл

@ -1,88 +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.AspNet.Mvc.Razor.Precompilation
{
/// <summary>
/// An entry in the cache used by <see cref="RazorPreCompiler"/>.
/// </summary>
public class PrecompilationCacheEntry
{
/// <summary>
/// Initializes a new instance of <see cref="PrecompilationCacheEntry"/> for a successful parse.
/// </summary>
/// <param name="fileInfo">The <see cref="RazorFileInfo"/> of the file being cached.</param>
/// <param name="syntaxTree">The <see cref="CodeAnalysis.SyntaxTree"/> to cache.</param>
public PrecompilationCacheEntry(
RazorFileInfo fileInfo,
SyntaxTree syntaxTree)
{
if (fileInfo == null)
{
throw new ArgumentNullException(nameof(fileInfo));
}
if (syntaxTree == null)
{
throw new ArgumentNullException(nameof(syntaxTree));
}
FileInfo = fileInfo;
SyntaxTree = syntaxTree;
}
/// <summary>
/// Initializes a new instance of <see cref="PrecompilationCacheEntry"/> for a failed parse.
/// </summary>
/// <param name="diagnostics">The <see cref="IReadOnlyList{Diagnostic}"/> produced from parsing the Razor
/// file. This does not contain <see cref="Diagnostic"/>s produced from compiling the parsed
/// <see cref="CodeAnalysis.SyntaxTree"/>.</param>
public PrecompilationCacheEntry(IReadOnlyList<Diagnostic> diagnostics)
{
if (diagnostics == null)
{
throw new ArgumentNullException(nameof(diagnostics));
}
Diagnostics = diagnostics;
}
/// <summary>
/// Gets the <see cref="RazorFileInfo"/> associated with this cache entry instance.
/// </summary>
/// <remarks>
/// This property is not <c>null</c> if <see cref="Success"/> is <c>true</c>.
/// </remarks>
public RazorFileInfo FileInfo { get; }
/// <summary>
/// Gets the <see cref="SyntaxTree"/> produced from parsing the Razor file.
/// </summary>
/// <remarks>
/// This property is not <c>null</c> if <see cref="Success"/> is <c>true</c>.
/// </remarks>
public SyntaxTree SyntaxTree { get; }
/// <summary>
/// Gets the <see cref="Diagnostic"/>s produced from parsing the generated contents of the file
/// specified by <see cref="FileInfo"/>. This does not contain <see cref="Diagnostic"/>s produced from
/// compiling the parsed <see cref="CodeAnalysis.SyntaxTree"/>.
/// </summary>
/// <remarks>
/// This property is <c>null</c> if <see cref="Success"/> is <c>true</c>.
/// </remarks>
public IReadOnlyList<Diagnostic> Diagnostics { get; }
/// <summary>
/// Gets a value that indicates if parsing was successful.
/// </summary>
public bool Success
{
get { return SyntaxTree != null; }
}
}
}

Просмотреть файл

@ -1,47 +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.AspNet.Razor;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.AspNet.Mvc.Razor.Precompilation
{
public static class RazorErrorExtensions
{
public static Diagnostic ToDiagnostics(this RazorError error, string filePath)
{
if (error == null)
{
throw new ArgumentNullException(nameof(error));
}
if (filePath == null)
{
throw new ArgumentNullException(nameof(filePath));
}
var descriptor = new DiagnosticDescriptor(
id: "Razor",
title: "Razor parsing error",
messageFormat: error.Message.Replace("{", "{{").Replace("}", "}}"),
category: "Razor.Parser",
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true);
var location = error.Location;
if (location.Equals(SourceLocation.Undefined))
{
location = SourceLocation.Zero;
}
var length = Math.Max(0, error.Length);
var textSpan = new TextSpan(location.AbsoluteIndex, length);
var linePositionStart = new LinePosition(location.LineIndex, location.CharacterIndex);
var linePositionEnd = new LinePosition(location.LineIndex, location.CharacterIndex + length);
var linePositionSpan = new LinePositionSpan(linePositionStart, linePositionEnd);
return Diagnostic.Create(descriptor, Location.Create(filePath, textSpan, linePositionSpan));
}
}
}

Просмотреть файл

@ -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.
namespace Microsoft.AspNet.Mvc.Razor.Precompilation
{
/// <summary>
/// Metadata for precompiled files.
/// </summary>
public class RazorFileInfo
{
/// <summary>
/// Type name including namespace.
/// </summary>
public string FullTypeName { get; set; }
/// <summary>
/// Path to to the file relative to the application base.
/// </summary>
public string RelativePath { get; set; }
}
}

Просмотреть файл

@ -1,63 +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.Reflection;
using Microsoft.Extensions.PlatformAbstractions;
namespace Microsoft.AspNet.Mvc.Razor.Precompilation
{
/// <summary>
/// Specifies metadata about precompiled views.
/// </summary>
public abstract class RazorFileInfoCollection
{
/// <summary>
/// Gets or sets the name of the resource containing the precompiled binary.
/// </summary>
public string AssemblyResourceName { get; protected set; }
/// <summary>
/// Gets or sets the name of the resource that contains the symbols (pdb).
/// </summary>
public string SymbolsResourceName { get; protected set; }
/// <summary>
/// Gets the <see cref="IReadOnlyList{T}"/> of <see cref="RazorFileInfo"/>s.
/// </summary>
public IReadOnlyList<RazorFileInfo> FileInfos { get; protected set; }
/// <summary>
/// Loads the assembly containing precompiled views.
/// </summary>
/// <param name="loadContext">The <see cref="IAssemblyLoadContext"/>.</param>
/// <returns>The <see cref="Assembly"/> containing precompiled views.</returns>
public virtual Assembly LoadAssembly(IAssemblyLoadContext loadContext)
{
var viewCollectionAssembly = GetType().GetTypeInfo().Assembly;
using (var assemblyStream = viewCollectionAssembly.GetManifestResourceStream(AssemblyResourceName))
{
if (assemblyStream == null)
{
var message = Resources.FormatRazorFileInfoCollection_ResourceCouldNotBeFound(AssemblyResourceName,
GetType().FullName);
throw new InvalidOperationException(message);
}
Stream symbolsStream = null;
if (!string.IsNullOrEmpty(SymbolsResourceName))
{
symbolsStream = viewCollectionAssembly.GetManifestResourceStream(SymbolsResourceName);
}
using (symbolsStream)
{
return loadContext.LoadStream(assemblyStream, symbolsStream);
}
}
}
}
}

Просмотреть файл

@ -1,121 +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.Runtime.Versioning;
using Microsoft.AspNet.FileProviders;
using Microsoft.Dnx.Compilation.CSharp;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Internal;
namespace Microsoft.AspNet.Mvc.Razor.Precompilation
{
/// <summary>
/// An <see cref="ICompileModule"/> implementation that pre-compiles Razor views in the application.
/// </summary>
public abstract class RazorPreCompileModule : ICompileModule
{
private const string ReleaseConfiguration = "release";
private readonly object _memoryCacheLookupLock = new object();
private readonly Dictionary<PrecompilationCacheKey, MemoryCache> _memoryCacheLookup =
new Dictionary<PrecompilationCacheKey, MemoryCache>();
/// <summary>
/// Gets or sets a value that determines if symbols (.pdb) file for the precompiled views is generated.
/// </summary>
public bool GenerateSymbols { get; protected set; }
/// <inheritdoc />
/// <remarks>Pre-compiles all Razor views in the application.</remarks>
public virtual void BeforeCompile(BeforeCompileContext context)
{
if (!EnablePreCompilation(context))
{
return;
}
MemoryCache memoryCache;
lock (_memoryCacheLookupLock)
{
var cacheKey = new PrecompilationCacheKey
{
Configuration = context.ProjectContext.Configuration,
TargetFramework = context.ProjectContext.TargetFramework
};
if (!_memoryCacheLookup.TryGetValue(cacheKey, out memoryCache))
{
// When CompactOnMemoryPressure is true, the MemoryCache evicts items at every gen2 collection.
// In DTH, gen2 happens frequently enough to make it undesirable for caching precompilation results. We'll
// disable listening for memory pressure for the MemoryCache instance used by precompilation.
memoryCache = new MemoryCache(new MemoryCacheOptions { CompactOnMemoryPressure = false });
_memoryCacheLookup[cacheKey] = memoryCache;
}
}
using (var fileProvider = new PhysicalFileProvider(context.ProjectContext.ProjectDirectory))
{
var viewCompiler = new RazorPreCompiler(
context,
fileProvider,
memoryCache)
{
GenerateSymbols = GenerateSymbols
};
viewCompiler.CompileViews();
}
}
/// <inheritdoc />
public void AfterCompile(AfterCompileContext context)
{
}
/// <summary>
/// Determines if this instance of <see cref="RazorPreCompileModule"/> should enable
/// compilation of views.
/// </summary>
/// <param name="context">The <see cref="BeforeCompileContext"/>.</param>
/// <returns><c>true</c> if views should be precompiled; otherwise <c>false</c>.</returns>
/// <remarks>Returns <c>true</c> if the current application is being built in <c>release</c>
/// configuration.</remarks>
protected virtual bool EnablePreCompilation(BeforeCompileContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
return string.Equals(
context.ProjectContext.Configuration,
ReleaseConfiguration,
StringComparison.OrdinalIgnoreCase);
}
private class PrecompilationCacheKey : IEquatable<PrecompilationCacheKey>
{
public string Configuration { get; set; }
public FrameworkName TargetFramework { get; set; }
public bool Equals(PrecompilationCacheKey other)
{
return
other.TargetFramework == TargetFramework &&
string.Equals(other.Configuration, Configuration, StringComparison.Ordinal);
}
public override int GetHashCode()
{
var hashCodeCombiner = HashCodeCombiner.Start();
hashCodeCombiner.Add(Configuration);
hashCodeCombiner.Add(TargetFramework);
return hashCodeCombiner;
}
}
}
}

Просмотреть файл

@ -1,356 +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.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.FileProviders;
using Microsoft.AspNet.Mvc.Internal;
using Microsoft.AspNet.Mvc.Razor.Compilation;
using Microsoft.AspNet.Mvc.Razor.Directives;
using Microsoft.AspNet.Mvc.Razor.Internal;
using Microsoft.AspNet.Razor.Runtime.Precompilation;
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.Dnx.Compilation.CSharp;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.CompilationAbstractions;
namespace Microsoft.AspNet.Mvc.Razor.Precompilation
{
public class RazorPreCompiler
{
private const string CacheKeyDirectorySeparator = "/";
private readonly TagHelperDescriptorFactory _tagHelperDescriptorFactory =
new TagHelperDescriptorFactory(designTime: false);
public RazorPreCompiler(
BeforeCompileContext compileContext,
IFileProvider fileProvider,
IMemoryCache precompilationCache)
{
if (compileContext == null)
{
throw new ArgumentNullException(nameof(compileContext));
}
if (fileProvider == null)
{
throw new ArgumentNullException(nameof(fileProvider));
}
if (precompilationCache == null)
{
throw new ArgumentNullException(nameof(precompilationCache));
}
CompileContext = compileContext;
FileProvider = fileProvider;
// There should always be a syntax tree even if there are no files (we generate one)
Debug.Assert(compileContext.Compilation.SyntaxTrees.Length > 0);
var defines = compileContext.Compilation.SyntaxTrees[0].Options.PreprocessorSymbolNames;
CompilationSettings = new CompilationSettings
{
CompilationOptions = compileContext.Compilation.Options,
Defines = defines,
LanguageVersion = compileContext.Compilation.LanguageVersion
};
PreCompilationCache = precompilationCache;
TagHelperTypeResolver = new PrecompilationTagHelperTypeResolver(CompileContext.Compilation);
}
/// <summary>
/// Gets or sets a value that determines if symbols (.pdb) file for the precompiled views is generated.
/// </summary>
public bool GenerateSymbols { get; set; }
protected IFileProvider FileProvider { get; }
protected BeforeCompileContext CompileContext { get; }
protected CompilationSettings CompilationSettings { get; }
protected IMemoryCache PreCompilationCache { get; }
protected virtual string FileExtension { get; } = ".cshtml";
protected virtual int MaxDegreesOfParallelism { get; } = Environment.ProcessorCount;
protected virtual TagHelperTypeResolver TagHelperTypeResolver { get; }
public virtual void CompileViews()
{
var result = CreateFileInfoCollection();
if (result != null)
{
var generatedCode = RazorFileInfoCollectionGenerator.GenerateCode(result);
var syntaxTree = CSharpSyntaxTree.ParseText(
generatedCode,
SyntaxTreeGenerator.GetParseOptions(CompilationSettings));
CompileContext.Compilation = CompileContext.Compilation.AddSyntaxTrees(syntaxTree);
}
}
protected virtual RazorFileInfoCollection CreateFileInfoCollection()
{
var filesToProcess = new List<RelativeFileInfo>();
GetFileInfosRecursive(root: string.Empty, razorFiles: filesToProcess);
if (filesToProcess.Count == 0)
{
return null;
}
var razorFiles = new RazorFileInfo[filesToProcess.Count];
var syntaxTrees = new SyntaxTree[filesToProcess.Count];
var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = MaxDegreesOfParallelism };
var diagnosticsLock = new object();
var hasErrors = false;
Parallel.For(0, filesToProcess.Count, parallelOptions, index =>
{
var file = filesToProcess[index];
PrecompilationCacheEntry cacheEntry;
if (!PreCompilationCache.TryGetValue(file.RelativePath, out cacheEntry))
{
cacheEntry = GetCacheEntry(file);
PreCompilationCache.Set(
file.RelativePath,
cacheEntry,
GetMemoryCacheEntryOptions(file, cacheEntry));
}
if (cacheEntry != null)
{
if (cacheEntry.Success)
{
syntaxTrees[index] = cacheEntry.SyntaxTree;
razorFiles[index] = cacheEntry.FileInfo;
}
else
{
hasErrors = true;
lock (diagnosticsLock)
{
AddRange(CompileContext.Diagnostics, cacheEntry.Diagnostics);
}
}
}
});
if (hasErrors)
{
// If any of the Razor files had syntax errors, don't emit the precompiled views assembly.
return null;
}
return GeneratePrecompiledAssembly(
syntaxTrees.Where(tree => tree != null),
razorFiles.Where(file => file != null));
}
protected virtual RazorFileInfoCollection GeneratePrecompiledAssembly(
IEnumerable<SyntaxTree> syntaxTrees,
IEnumerable<RazorFileInfo> razorFileInfos)
{
if (syntaxTrees == null)
{
throw new ArgumentNullException(nameof(syntaxTrees));
}
if (razorFileInfos == null)
{
throw new ArgumentNullException(nameof(razorFileInfos));
}
var resourcePrefix = string.Join(".", CompileContext.Compilation.AssemblyName,
nameof(RazorPreCompiler),
Path.GetRandomFileName());
var assemblyResourceName = resourcePrefix + ".dll";
var applicationReference = CompileContext.Compilation.ToMetadataReference();
var references = CompileContext.Compilation.References
.Concat(new[] { applicationReference });
var preCompilationOptions = CompilationSettings
.CompilationOptions
.WithOutputKind(OutputKind.DynamicallyLinkedLibrary);
var compilation = CSharpCompilation.Create(
assemblyResourceName,
options: preCompilationOptions,
syntaxTrees: syntaxTrees,
references: references);
var generateSymbols = GenerateSymbols && SymbolsUtility.SupportsSymbolsGeneration();
// These streams are returned to the runtime and consequently cannot be disposed.
var assemblyStream = new MemoryStream();
var pdbStream = generateSymbols ? new MemoryStream() : null;
var emitResult = compilation.Emit(assemblyStream, pdbStream);
if (!emitResult.Success)
{
AddRange(CompileContext.Diagnostics, emitResult.Diagnostics);
return null;
}
else
{
var assemblyResource = new ResourceDescriptor()
{
FileName = Path.GetFileName(assemblyResourceName),
Name = assemblyResourceName,
StreamFactory = () => GetNonDisposableStream(assemblyStream)
};
CompileContext.Resources.Add(assemblyResource);
string symbolsResourceName = null;
if (pdbStream != null)
{
symbolsResourceName = resourcePrefix + ".pdb";
var pdbResource = new ResourceDescriptor()
{
FileName = Path.GetFileName(symbolsResourceName),
Name = symbolsResourceName,
StreamFactory = () => GetNonDisposableStream(pdbStream)
};
CompileContext.Resources.Add(pdbResource);
}
return new PrecompileRazorFileInfoCollection(assemblyResourceName,
symbolsResourceName,
razorFileInfos.ToList());
}
}
protected IMvcRazorHost GetRazorHost()
{
var descriptorResolver = new TagHelperDescriptorResolver(
TagHelperTypeResolver,
_tagHelperDescriptorFactory);
return new MvcRazorHost(new DefaultChunkTreeCache(FileProvider))
{
TagHelperDescriptorResolver = descriptorResolver
};
}
private MemoryCacheEntryOptions GetMemoryCacheEntryOptions(
RelativeFileInfo fileInfo,
PrecompilationCacheEntry cacheEntry)
{
var options = new MemoryCacheEntryOptions();
options.AddExpirationToken(FileProvider.Watch(fileInfo.RelativePath));
foreach (var path in ViewHierarchyUtility.GetViewImportsLocations(fileInfo.RelativePath))
{
options.AddExpirationToken(FileProvider.Watch(path));
}
return options;
}
private void GetFileInfosRecursive(string root, List<RelativeFileInfo> razorFiles)
{
var fileInfos = FileProvider.GetDirectoryContents(root);
foreach (var fileInfo in fileInfos)
{
if (fileInfo.IsDirectory)
{
var subPath = CombinePath(root, fileInfo.Name);
GetFileInfosRecursive(subPath, razorFiles);
}
else if (Path.GetExtension(fileInfo.Name)
.Equals(FileExtension, StringComparison.OrdinalIgnoreCase))
{
var relativePath = CombinePath(root, fileInfo.Name);
var info = new RelativeFileInfo(fileInfo, relativePath);
razorFiles.Add(info);
}
}
}
protected virtual PrecompilationCacheEntry GetCacheEntry(RelativeFileInfo fileInfo)
{
if (fileInfo == null)
{
throw new ArgumentNullException(nameof(fileInfo));
}
using (var stream = fileInfo.FileInfo.CreateReadStream())
{
using (var host = GetRazorHost())
{
var results = host.GenerateCode(fileInfo.RelativePath, stream);
if (results.Success)
{
var syntaxTree = SyntaxTreeGenerator.Generate(
results.GeneratedCode,
fileInfo.FileInfo.PhysicalPath,
CompilationSettings);
var fullTypeName = results.GetMainClassName(host, syntaxTree);
if (fullTypeName != null)
{
var razorFileInfo = new RazorFileInfo
{
RelativePath = fileInfo.RelativePath,
FullTypeName = fullTypeName
};
return new PrecompilationCacheEntry(razorFileInfo, syntaxTree);
}
}
else
{
var diagnostics = results
.ParserErrors
.Select(error => error.ToDiagnostics(fileInfo.FileInfo.PhysicalPath))
.ToList();
return new PrecompilationCacheEntry(diagnostics);
}
}
}
return null;
}
private static void AddRange<TVal>(IList<TVal> target, IEnumerable<TVal> source)
{
foreach (var diagnostic in source)
{
target.Add(diagnostic);
}
}
private static Stream GetNonDisposableStream(Stream stream)
{
stream.Position = 0;
return new NonDisposableStream(stream);
}
private static string CombinePath(string root, string name)
{
// We use string.Join instead of Path.Combine here to ensure that the path
// separator we produce matches the one used by the CompilerCache.
return string.Join(CacheKeyDirectorySeparator, root, name);
}
private class PrecompileRazorFileInfoCollection : RazorFileInfoCollection
{
public PrecompileRazorFileInfoCollection(
string assemblyResourceName,
string symbolsResourceName,
IReadOnlyList<RazorFileInfo> fileInfos)
{
AssemblyResourceName = assemblyResourceName;
SymbolsResourceName = symbolsResourceName;
FileInfos = fileInfos;
}
}
}
}

Просмотреть файл

@ -13,7 +13,6 @@
"Microsoft.AspNet.FileProviders.Composite": "1.0.0-*",
"Microsoft.AspNet.Mvc.Razor.Host": "6.0.0-*",
"Microsoft.AspNet.Mvc.ViewFeatures": "6.0.0-*",
"Microsoft.AspNet.Razor.Runtime.Precompilation": "4.0.0-*",
"Microsoft.Extensions.HashCodeCombiner.Sources": {
"version": "1.0.0-*",
"type": "build"

Просмотреть файл

@ -1,137 +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 System.Net;
using System.Net.Http;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.Razor.Precompilation;
using Microsoft.AspNet.Testing.xunit;
using PrecompilationWebSite;
using Xunit;
namespace Microsoft.AspNet.Mvc.FunctionalTests
{
public class PrecompilationTest : IClassFixture<MvcTestFixture<PrecompilationWebSite.Startup>>
{
public PrecompilationTest(MvcTestFixture<PrecompilationWebSite.Startup> fixture)
{
Client = fixture.Client;
}
public HttpClient Client { get; }
[ConditionalFact]
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
public async Task PrecompiledView_RendersCorrectly()
{
// Arrange
// We will render a view that writes the fully qualified name of the Assembly containing the type of
// the view. If the view is precompiled, this assembly will be PrecompilationWebsite.
var assemblyNamePrefix = GetAssemblyNamePrefix();
// Act
var response = await Client.GetAsync("http://localhost/Home/Index");
var responseContent = await response.Content.ReadAsStringAsync();
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var parsedResponse1 = new ParsedResponse(responseContent);
Assert.StartsWith(assemblyNamePrefix, parsedResponse1.ViewStart);
Assert.StartsWith(assemblyNamePrefix, parsedResponse1.Layout);
Assert.StartsWith(assemblyNamePrefix, parsedResponse1.Index);
}
[Fact]
public async Task PrecompiledView_UsesCompilationOptionsFromApplication()
{
// Arrange
var assemblyNamePrefix = GetAssemblyNamePrefix();
#if DNX451
var expected =
@"Value set inside DNX451 " + assemblyNamePrefix;
#elif DNXCORE50
var expected =
@"Value set inside DNXCORE50 " + assemblyNamePrefix;
#endif
// Act
var response = await Client.GetAsync("http://localhost/Home/PrecompiledViewsCanConsumeCompilationOptions");
var responseContent = await response.Content.ReadAsStringAsync();
// Assert
Assert.StartsWith(expected, responseContent.Trim());
}
[ConditionalFact]
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
public async Task TagHelpersFromTheApplication_CanBeAdded()
{
// Arrange
var assemblyNamePrefix = GetAssemblyNamePrefix();
var expected =
@"<root data-root=""true""><input class=""form-control"" type=""number"" data-val=""true""" +
@" data-val-range=""The field Age must be between 10 and 100."" data-val-range-max=""100"" "+
@"data-val-range-min=""10"" data-val-required=""The Age field is required."" " +
@"id=""Age"" name=""Age"" value="""" /><a href=""/TagHelpers"">Back to List</a></root>";
// Act
var response = await Client.GetStringAsync("http://localhost/TagHelpers/Add");
// Assert
var responseLines = response.Split(new[] { "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries);
Assert.StartsWith(assemblyNamePrefix, responseLines[0]);
Assert.Equal(expected, responseLines[1]);
}
[ConditionalFact]
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
public async Task TagHelpersFromTheApplication_CanBeRemoved()
{
// Arrange
var assemblyNamePrefix = GetAssemblyNamePrefix();
var expected = @"<root>root-content</root>";
// Act
var response = await Client.GetStringAsync("http://localhost/TagHelpers/Remove");
// Assert
var responseLines = response.Split(new[] { "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries);
Assert.StartsWith(assemblyNamePrefix, responseLines[0]);
Assert.Equal(expected, responseLines[1]);
}
private static string GetAssemblyNamePrefix()
{
return typeof(Startup).GetTypeInfo().Assembly.GetName().Name + "." + nameof(RazorPreCompiler) + ".";
}
private sealed class ParsedResponse
{
public ParsedResponse(string responseContent)
{
var results = responseContent
.Split(new[] { "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries)
.Select(s => s.Trim())
.ToArray();
Assert.True(results[0].StartsWith("Layout:"));
Layout = results[0].Substring("Layout:".Length);
Assert.True(results[1].StartsWith("_viewstart:"));
ViewStart = results[1].Substring("_viewstart:".Length);
Assert.True(results[2].StartsWith("index:"));
Index = results[2].Substring("index:".Length);
}
public string Layout { get; }
public string ViewStart { get; }
public string Index { get; }
}
}
}

Просмотреть файл

@ -37,7 +37,6 @@
"Microsoft.Extensions.Logging.Testing": "1.0.0-*",
"MvcSandbox": "1.0.0",
"MvcSubAreaSample.Web": "1.0.0",
"PrecompilationWebSite": "1.0.0",
"RazorPageExecutionInstrumentationWebSite": "1.0.0",
"RazorWebSite": "1.0.0",
"RoutingWebSite": "1.0.0",

Просмотреть файл

@ -1,142 +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.Reflection;
using Microsoft.AspNet.Mvc.Razor.Precompilation;
using Microsoft.Extensions.PlatformAbstractions;
using Moq;
using Xunit;
namespace Microsoft.AspNet.Mvc.Razor.Compilation
{
public class PrecompiledViewsCompilerCacheProviderTest
{
[Fact]
public void IsValidRazorFileInfoCollection_ReturnsFalse_IfTypeIsAbstract()
{
// Arrange
var type = typeof(AbstractRazorFileInfoCollection);
// Act
var result = PrecompiledViewsCompilerCacheProvider.IsValidRazorFileInfoCollection(type);
// Assert
Assert.False(result);
}
[Fact]
public void IsValidRazorFileInfoCollection_ReturnsFalse_IfTypeHasGenericParameters()
{
// Arrange
var type = typeof(GenericRazorFileInfoCollection<>);
// Act
var result = PrecompiledViewsCompilerCacheProvider.IsValidRazorFileInfoCollection(type);
// Assert
Assert.False(result);
}
[Fact]
public void IsValidRazorFileInfoCollection_ReturnsFalse_IfTypeDoesNotDeriveFromRazorFileInfoCollection()
{
// Arrange
var type = typeof(NonSubTypeRazorFileInfoCollection);
// Act
var result = PrecompiledViewsCompilerCacheProvider.IsValidRazorFileInfoCollection(type);
// Assert
Assert.False(result);
}
[Theory]
[InlineData(typeof(ParameterConstructorRazorFileInfoCollection))]
[InlineData(typeof(ViewCollection))]
public void IsValidRazorFileInfoCollection_ReturnsTrue_IfTypeDerivesFromRazorFileInfoCollection(Type type)
{
// Act
var result = PrecompiledViewsCompilerCacheProvider.IsValidRazorFileInfoCollection(type);
// Assert
Assert.True(result);
}
[Fact]
public void GetPrecompiledViews_ReturnsTypesSpecifiedByRazorFileInfoCollections()
{
// Arrange
var fileInfoCollections = new[] { new ViewCollection() };
// Act
var precompiledViews = PrecompiledViewsCompilerCacheProvider.GetPrecompiledViews(
fileInfoCollections,
Mock.Of<IAssemblyLoadContext>());
// Assert
Assert.Equal(2, precompiledViews.Count);
Type type;
Assert.True(precompiledViews.TryGetValue("Views/Home/Index.cshtml", out type));
Assert.Equal(typeof(TestView1), type);
Assert.True(precompiledViews.TryGetValue("Views/Home/About.cshtml", out type));
Assert.Equal(typeof(TestView2), type);
}
private abstract class AbstractRazorFileInfoCollection : RazorFileInfoCollection
{
}
private class GenericRazorFileInfoCollection<TVal> : RazorFileInfoCollection
{
}
private class ParameterConstructorRazorFileInfoCollection : RazorFileInfoCollection
{
public ParameterConstructorRazorFileInfoCollection(string value)
{
}
}
private class NonSubTypeRazorFileInfoCollection : Controller
{
}
private class ViewCollection : RazorFileInfoCollection
{
public ViewCollection()
{
FileInfos = new[]
{
new RazorFileInfo
{
FullTypeName = typeof(TestView1).FullName,
RelativePath = "Views/Home/Index.cshtml"
},
new RazorFileInfo
{
FullTypeName = typeof(TestView2).FullName,
RelativePath = "Views/Home/About.cshtml"
},
};
}
public override Assembly LoadAssembly(IAssemblyLoadContext loadContext)
{
return GetType().GetTypeInfo().Assembly;
}
}
private class TestView1
{
}
private class TestView2
{
}
}
}

Просмотреть файл

@ -1,135 +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.AspNet.Mvc.Razor.Compilation;
using Microsoft.AspNet.Mvc.Razor.Precompilation;
using Microsoft.CodeAnalysis.CSharp;
using Xunit;
namespace Microsoft.AspNet.Mvc.Razor.Internal
{
public class RazorFileInfoCollectionGeneratorTest
{
public static TheoryData GenerateCollection_ProducesExpectedCodeData
{
get
{
var expected1 =
@"namespace __ASP_ASSEMBLY
{
[System.Runtime.CompilerServices.CompilerGeneratedAttribute]
public class __PreGeneratedViewCollection : Microsoft.AspNet.Mvc.Razor.Precompilation.RazorFileInfoCollection
{
public __PreGeneratedViewCollection()
{
AssemblyResourceName = @""EmptyAssembly"";
SymbolsResourceName = @"""";
FileInfos = new System.Collections.Generic.List<Microsoft.AspNet.Mvc.Razor.Precompilation.RazorFileInfo>
{
};
}
private static System.Reflection.Assembly _loadedAssembly;
public override System.Reflection.Assembly LoadAssembly(
Microsoft.Extensions.PlatformAbstractions.IAssemblyLoadContext loadContext)
{
if (_loadedAssembly == null)
{
_loadedAssembly = base.LoadAssembly(loadContext);
}
return _loadedAssembly;
}
}
}";
var expected2 =
@"namespace __ASP_ASSEMBLY
{
[System.Runtime.CompilerServices.CompilerGeneratedAttribute]
public class __PreGeneratedViewCollection : Microsoft.AspNet.Mvc.Razor.Precompilation.RazorFileInfoCollection
{
public __PreGeneratedViewCollection()
{
AssemblyResourceName = @""TestAssembly"";
SymbolsResourceName = @""SymbolsResource"";
FileInfos = new System.Collections.Generic.List<Microsoft.AspNet.Mvc.Razor.Precompilation.RazorFileInfo>
{
new Microsoft.AspNet.Mvc.Razor.Precompilation.RazorFileInfo
{
FullTypeName = @""SomeType.Name"",
RelativePath = @""Views/Home/Index.cshtml""
},
new Microsoft.AspNet.Mvc.Razor.Precompilation.RazorFileInfo
{
FullTypeName = @""Different.Name"",
RelativePath = @""Views/Home/Different.cshtml""
},
};
}
private static System.Reflection.Assembly _loadedAssembly;
public override System.Reflection.Assembly LoadAssembly(
Microsoft.Extensions.PlatformAbstractions.IAssemblyLoadContext loadContext)
{
if (_loadedAssembly == null)
{
_loadedAssembly = base.LoadAssembly(loadContext);
}
return _loadedAssembly;
}
}
}";
return new TheoryData<RazorFileInfoCollection, string>
{
{ new EmptyCollection(), expected1 },
{ new TestCollection(), expected2 },
};
}
}
[Theory]
[MemberData(nameof(GenerateCollection_ProducesExpectedCodeData))]
public void GenerateCollection_ProducesExpectedCode(RazorFileInfoCollection collection, string expected)
{
// Act
var actual = RazorFileInfoCollectionGenerator.GenerateCode(collection);
// Assert
Assert.Equal(expected, actual);
}
private class EmptyCollection : RazorFileInfoCollection
{
public EmptyCollection()
{
AssemblyResourceName = "EmptyAssembly";
FileInfos = new List<RazorFileInfo>();
}
}
private class TestCollection : RazorFileInfoCollection
{
public TestCollection()
{
AssemblyResourceName = "TestAssembly";
SymbolsResourceName = "SymbolsResource";
FileInfos = new List<RazorFileInfo>
{
new RazorFileInfo
{
FullTypeName = "SomeType.Name",
RelativePath = @"Views/Home/Index.cshtml"
},
new RazorFileInfo
{
FullTypeName = "Different.Name",
RelativePath = @"Views/Home/Different.cshtml"
},
};
}
}
}
}

Просмотреть файл

@ -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.AspNet.Razor;
using Xunit;
namespace Microsoft.AspNet.Mvc.Razor.Precompilation
{
public class RazorErrorExtensionsTest
{
public static TheoryData ToDiagnostic_SucceedsWhenRazorErrorLocationIsZeroOrUndefinedData
{
get
{
return new TheoryData<SourceLocation, int>
{
{ SourceLocation.Undefined, -1 },
{ SourceLocation.Undefined, 0 },
{ SourceLocation.Zero, -1 },
{ SourceLocation.Zero, 0 },
};
}
}
[Theory]
[MemberData(nameof(ToDiagnostic_SucceedsWhenRazorErrorLocationIsZeroOrUndefinedData))]
public void ToDiagnostic_SucceedsWhenRazorErrorLocationIsZeroOrUndefined(
SourceLocation location,
int length)
{
// Arrange
var error = new RazorError("some message", location, length);
// Act
var diagnostics = error.ToDiagnostics("/some-path");
// Assert
var span = diagnostics.Location.GetMappedLineSpan();
Assert.Equal("/some-path", span.Path);
Assert.Equal(0, span.StartLinePosition.Line);
Assert.Equal(0, span.StartLinePosition.Character);
Assert.Equal(0, span.EndLinePosition.Line);
Assert.Equal(0, span.EndLinePosition.Character);
}
[Fact]
public void ToDiagnostic_ConvertsRazorErrorLocation_ToSourceLineMappings()
{
// Arrange
var sourceLocation = new SourceLocation(absoluteIndex: 30, lineIndex: 10, characterIndex: 1);
var error = new RazorError("some message", sourceLocation, length: 5);
// Act
var diagnostics = error.ToDiagnostics("/some-path");
// Assert
var span = diagnostics.Location.GetMappedLineSpan();
Assert.Equal("/some-path", span.Path);
Assert.Equal(10, span.StartLinePosition.Line);
Assert.Equal(1, span.StartLinePosition.Character);
Assert.Equal(10, span.EndLinePosition.Line);
Assert.Equal(6, span.EndLinePosition.Character);
}
}
}

Просмотреть файл

@ -1 +0,0 @@
*.cshtml

Просмотреть файл

@ -1,31 +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.AspNet.Mvc;
namespace PrecompilationWebSite.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
public IActionResult PrecompiledViewsCanConsumeCompilationOptions()
{
return View("~/Views/ViewsConsumingCompilationOptions/Index.cshtml");
}
public IActionResult GlobalDeletedPriorToFirstRequest()
{
return View("~/Views/ViewImportsDelete/Index.cshtml");
}
[HttpGet("/Test")]
public IActionResult TestView()
{
return View("~/Views/Test/Index.cshtml");
}
}
}

Просмотреть файл

@ -1,20 +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.AspNet.Mvc;
namespace PrecompilationWebSite.Controllers
{
public class TagHelpersController : Controller
{
public IActionResult Add()
{
return View();
}
public IActionResult Remove()
{
return View();
}
}
}

Просмотреть файл

@ -1,13 +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.ComponentModel.DataAnnotations;
namespace PrecompilationWebSite.Models
{
public class Person
{
[Range(10, 100)]
public int Age { get; set; }
}
}

Просмотреть файл

@ -1,39 +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.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.Extensions.DependencyInjection;
namespace PrecompilationWebSite
{
public class Startup
{
// Set up application services
public void ConfigureServices(IServiceCollection services)
{
// Add MVC services to the services container
services
.AddMvc()
.AddPrecompiledRazorViews(GetType().GetTypeInfo().Assembly);
}
public void Configure(IApplicationBuilder app)
{
app.UseCultureReplacer();
app.UseMvcWithDefaultRoute();
}
public static void Main(string[] args)
{
var application = new WebApplicationBuilder()
.UseConfiguration(WebApplicationConfiguration.GetDefault(args))
.UseStartup<Startup>()
.Build();
application.Run();
}
}
}

Просмотреть файл

@ -1,16 +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.AspNet.Razor.TagHelpers;
namespace PrecompilationWebSite.TagHelpers
{
[HtmlTargetElement("root")]
public class RootViewStartTagHelper : TagHelper
{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.Attributes["data-root"] = "true";
}
}
}

Просмотреть файл

@ -1 +0,0 @@
index:@GetType().GetTypeInfo().Assembly.GetName()

Просмотреть файл

@ -1,2 +0,0 @@
Layout:@GetType().GetTypeInfo().Assembly.FullName
@RenderBody()

Просмотреть файл

@ -1 +0,0 @@
@using System.Reflection

Просмотреть файл

@ -1,2 +0,0 @@
@{ Layout = "/Views/Home/Layout.cshtml";}
_viewstart:@GetType().GetTypeInfo().Assembly.FullName

Просмотреть файл

@ -1,3 +0,0 @@
@model PrecompilationWebSite.Models.Person
@addTagHelper *, Microsoft.AspNet.Mvc.TagHelpers
<root><input asp-for="Age" class="form-control" /><a asp-action="Index">Back to List</a></root>

Просмотреть файл

@ -1,2 +0,0 @@
@removeTagHelper *, PrecompilationWebSite
<root>root-content</root>

Просмотреть файл

@ -1 +0,0 @@
@addTagHelper PrecompilationWebSite.TagHelpers.RootViewStartTagHelper, PrecompilationWebSite

Просмотреть файл

@ -1,2 +0,0 @@
@using System.Reflection
@GetType().GetTypeInfo().Assembly.FullName

Просмотреть файл

@ -1 +0,0 @@
Test

Просмотреть файл

@ -1,2 +0,0 @@
@using System.Reflection;
@GetType().GetTypeInfo().Assembly.FullName

Просмотреть файл

@ -1 +0,0 @@
_ViewStart content

Просмотреть файл

@ -1,9 +0,0 @@
@{
string message =
#if DNX451
"Value set inside DNX451 " + GetType().Assembly.FullName;
#elif DNXCORE50
"Value set inside DNXCORE50 " + System.Reflection.IntrospectionExtensions.GetTypeInfo(GetType()).Assembly.FullName;
#endif
}
@message

Просмотреть файл

@ -1,13 +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.AspNet.Mvc.Razor.Precompilation;
using Microsoft.Dnx.Compilation.CSharp;
namespace PrecompilationWebSite
{
public class RazorPreCompilation : RazorPreCompileModule
{
protected override bool EnablePreCompilation(BeforeCompileContext context) => true;
}
}

Просмотреть файл

@ -1,3 +0,0 @@
{
"server": "Microsoft.AspNet.Server.Kestrel"
}

Просмотреть файл

@ -1,31 +0,0 @@
{
"commands": {
"web": "PrecompilationWebSite"
},
"compilationOptions": {
"emitEntryPoint": true
},
"dependencies": {
"Microsoft.AspNet.Mvc": "6.0.0-*",
"Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-*",
"Microsoft.AspNet.Mvc.TestConfiguration": "1.0.0",
"Microsoft.AspNet.Server.Kestrel": "1.0.0-*",
"Microsoft.AspNet.StaticFiles": "1.0.0-*",
"Microsoft.Extensions.PropertyHelper.Sources": {
"version": "1.0.0-*",
"type": "build"
}
},
"frameworks": {
"dnx451": {
"compilationOptions": {
"define": [ "CUSTOM_DNX451_DEFINE" ]
}
},
"dnxcore50": {
"compilationOptions": {
"define": [ "CUSTOM_DNXCORE50_DEFINE" ]
}
}
}
}

Просмотреть файл

@ -1,4 +0,0 @@
PreCompilationWebSite
===
This web site illustrates use cases for precompilation of razor pages.

Просмотреть файл

@ -1 +0,0 @@
HelloWorld