Adding Razor Precompilation

This commit is contained in:
Pranav K 2016-08-16 15:11:53 -07:00
parent 6f5722366d
commit dbe93ac6b1
75 changed files with 2805 additions and 2 deletions

3
.gitignore vendored
View File

@ -35,4 +35,5 @@ nuget.exe
*.sln.ide
node_modules
*launchSettings.json
*.orig
*.orig
BuildInfo.generated.cs

49
MvcPrecompilation.sln Normal file
View File

@ -0,0 +1,49 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design", "src\Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design\Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design.xproj", "{4339FC9B-AEC6-442A-B413-A41555ED76C7}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionFiles", "SolutionFiles", "{01707B64-7DC7-4B5A-B0BB-7CD2773AA297}"
ProjectSection(SolutionItems) = preProject
global.json = global.json
NuGet.config = NuGet.config
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{02F7AA35-91AF-491E-9F0E-03CFAF86C720}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Mvc.Razor.Precompilation.Tools", "src\Microsoft.AspNetCore.Mvc.Razor.Precompilation.Tools\Microsoft.AspNetCore.Mvc.Razor.Precompilation.Tools.xproj", "{F8BF7D95-0633-407F-BB0B-02563F13C068}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{0398AFFF-505E-4283-89DA-BBD9D28B53DB}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Mvc.Razor.Precompilation.Tests", "test\Microsoft.AspNetCore.Mvc.Razor.Precompilation.Tests\Microsoft.AspNetCore.Mvc.Razor.Precompilation.Tests.xproj", "{46C9A4B2-8B1C-451B-B670-C194901D66AC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4339FC9B-AEC6-442A-B413-A41555ED76C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4339FC9B-AEC6-442A-B413-A41555ED76C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4339FC9B-AEC6-442A-B413-A41555ED76C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4339FC9B-AEC6-442A-B413-A41555ED76C7}.Release|Any CPU.Build.0 = Release|Any CPU
{F8BF7D95-0633-407F-BB0B-02563F13C068}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F8BF7D95-0633-407F-BB0B-02563F13C068}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F8BF7D95-0633-407F-BB0B-02563F13C068}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F8BF7D95-0633-407F-BB0B-02563F13C068}.Release|Any CPU.Build.0 = Release|Any CPU
{46C9A4B2-8B1C-451B-B670-C194901D66AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{46C9A4B2-8B1C-451B-B670-C194901D66AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{46C9A4B2-8B1C-451B-B670-C194901D66AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{46C9A4B2-8B1C-451B-B670-C194901D66AC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{4339FC9B-AEC6-442A-B413-A41555ED76C7} = {02F7AA35-91AF-491E-9F0E-03CFAF86C720}
{F8BF7D95-0633-407F-BB0B-02563F13C068} = {02F7AA35-91AF-491E-9F0E-03CFAF86C720}
{46C9A4B2-8B1C-451B-B670-C194901D66AC} = {0398AFFF-505E-4283-89DA-BBD9D28B53DB}
EndGlobalSection
EndGlobal

16
NuGetPackageVerifier.json Normal file
View File

@ -0,0 +1,16 @@
{
"adx": { // Packages written by the ADX team and that ship on NuGet.org
"rules": [
"AdxVerificationCompositeRule"
],
"packages": {
"Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design": { },
"Microsoft.AspNetCore.Mvc.Razor.Precompilation.Tools": { }
}
},
"Default": { // Rules to run for packages not listed in any other set.
"rules": [
"DefaultCompositeRule"
]
}
}

46
TestApps.sln Normal file
View File

@ -0,0 +1,46 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "SimpleApp", "testapps\SimpleApp\SimpleApp.xproj", "{8FA176ED-C29E-48D6-BC7A-1C3A862CB15F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionItems", "{43488AEE-CCF2-4A90-B890-05320282BE29}"
ProjectSection(SolutionItems) = preProject
testapps\global.json = testapps\global.json
testapps\NuGet.config = testapps\NuGet.config
EndProjectSection
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ApplicationWithTagHelpers", "testapps\ApplicationWithTagHelpers\ApplicationWithTagHelpers.xproj", "{2079872F-E8F9-4DB1-A340-C0D897807B86}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ClassLibraryTagHelper", "testapps\ClassLibraryTagHelper\ClassLibraryTagHelper.xproj", "{39EFA075-3673-49AB-95F3-AA5E88DF6C30}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ApplicationWithConfigureMvc", "testapps\ApplicationWithConfigureMvc\ApplicationWithConfigureMvc.xproj", "{E2EAEB85-91D5-478E-9CE2-964F68DE20D0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8FA176ED-C29E-48D6-BC7A-1C3A862CB15F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8FA176ED-C29E-48D6-BC7A-1C3A862CB15F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8FA176ED-C29E-48D6-BC7A-1C3A862CB15F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8FA176ED-C29E-48D6-BC7A-1C3A862CB15F}.Release|Any CPU.Build.0 = Release|Any CPU
{2079872F-E8F9-4DB1-A340-C0D897807B86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2079872F-E8F9-4DB1-A340-C0D897807B86}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2079872F-E8F9-4DB1-A340-C0D897807B86}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2079872F-E8F9-4DB1-A340-C0D897807B86}.Release|Any CPU.Build.0 = Release|Any CPU
{39EFA075-3673-49AB-95F3-AA5E88DF6C30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{39EFA075-3673-49AB-95F3-AA5E88DF6C30}.Debug|Any CPU.Build.0 = Debug|Any CPU
{39EFA075-3673-49AB-95F3-AA5E88DF6C30}.Release|Any CPU.ActiveCfg = Release|Any CPU
{39EFA075-3673-49AB-95F3-AA5E88DF6C30}.Release|Any CPU.Build.0 = Release|Any CPU
{E2EAEB85-91D5-478E-9CE2-964F68DE20D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E2EAEB85-91D5-478E-9CE2-964F68DE20D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E2EAEB85-91D5-478E-9CE2-964F68DE20D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E2EAEB85-91D5-478E-9CE2-964F68DE20D0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

2
build.cmd Normal file
View File

@ -0,0 +1,2 @@
@ECHO OFF
PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*; exit $LASTEXITCODE"

View File

@ -1,3 +1,3 @@
{
"projects": ["src", "test/WebSites", "samples"]
"projects": ["src", "samples"]
}

9
makefile.shade Normal file
View File

@ -0,0 +1,9 @@
use namespace="System.IO"
-BuildQuality = "preview3";
use-standard-lifecycle
k-standard-goals
#repo-initialize target='initialize'
dotnet command='restore src test ${E("KOREBUILD_DOTNET_RESTORE_OPTIONS")}' workingDir='${Directory.GetCurrentDirectory()}' if='!NoRestore'

View File

@ -0,0 +1,39 @@
// 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.CommandLineUtils;
namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design.Internal
{
public class CommonOptions
{
public static readonly string ConfigureCompilationTypeTemplate = "--configure-compilation-type";
public static readonly string ContentRootTemplate = "--content-root";
public CommandArgument ProjectArgument { get; private set; }
public CommandOption ConfigureCompilationType { get; private set; }
public CommandOption ContentRootOption { get; private set; }
public void Configure(CommandLineApplication app)
{
app.Description = "Precompiles an application.";
app.HelpOption("-?|-h|--help");
ProjectArgument = app.Argument(
"project",
"The path to the project (project folder or project.json) with precompilation.");
ConfigureCompilationType = app.Option(
ConfigureCompilationTypeTemplate,
"Type with Configure method",
CommandOptionType.SingleValue);
ContentRootOption = app.Option(
ContentRootTemplate,
"The application's content root.",
CommandOptionType.SingleValue);
}
}
}

View File

@ -0,0 +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.
#if DEBUG
using System;
using System.Diagnostics;
using System.Linq;
namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design.Internal
{
public static class DebugHelper
{
public static void HandleDebugSwitch(ref string[] args)
{
if (args.Length > 0 && string.Equals("--debug", args[0], StringComparison.OrdinalIgnoreCase))
{
args = args.Skip(1).ToArray();
Console.WriteLine("Waiting for debugger to attach. Press ENTER to continue");
Console.WriteLine($"Process ID: {Process.GetCurrentProcess().Id}");
Console.ReadLine();
}
}
}
}
#endif

View File

@ -0,0 +1,116 @@
// 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 System.Reflection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Internal;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Mvc.Razor.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.ObjectPool;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design.Internal
{
public class MvcServiceProvider
{
private readonly string _projectPath;
private readonly string _contentRoot;
private readonly string _applicationName;
public MvcServiceProvider(
string projectPath,
string applicationName,
string contentRoot,
string configureCompilationType)
{
_projectPath = projectPath;
_contentRoot = contentRoot;
_applicationName = applicationName;
var mvcBuilderConfiguration = GetConfigureCompilationAction(configureCompilationType);
var serviceProvider = GetProvider(mvcBuilderConfiguration);
Host = serviceProvider.GetRequiredService<IMvcRazorHost>();
Compiler = serviceProvider.GetRequiredService<CSharpCompiler>();
ViewEngineOptions = serviceProvider.GetRequiredService<IOptions<RazorViewEngineOptions>>().Value;
FileProvider = serviceProvider.GetRequiredService<IRazorViewEngineFileProviderAccessor>().FileProvider;
}
public IMvcRazorHost Host { get; }
public CSharpCompiler Compiler { get; }
public IFileProvider FileProvider { get; }
public RazorViewEngineOptions ViewEngineOptions { get; }
private IDesignTimeMvcBuilderConfiguration GetConfigureCompilationAction(string configureCompilationType)
{
Type type;
if (!string.IsNullOrEmpty(configureCompilationType))
{
type = Type.GetType(configureCompilationType);
if (type == null)
{
throw new InvalidOperationException($"Unable to find type '{type}.");
}
}
else
{
var assemblyName = new AssemblyName(_applicationName);
var assembly = Assembly.Load(assemblyName);
type = assembly
.GetExportedTypes()
.FirstOrDefault(typeof(IDesignTimeMvcBuilderConfiguration).IsAssignableFrom);
}
if (type == null)
{
return null;
}
var instance = Activator.CreateInstance(type) as IDesignTimeMvcBuilderConfiguration;
if (instance == null)
{
throw new InvalidOperationException($"Type {configureCompilationType} does not implement " +
$"{typeof(IDesignTimeMvcBuilderConfiguration)}.");
}
return instance;
}
private IServiceProvider GetProvider(IDesignTimeMvcBuilderConfiguration mvcBuilderConfiguration)
{
var services = new ServiceCollection();
var hostingEnvironment = new HostingEnvironment
{
ApplicationName = _applicationName,
WebRootFileProvider = new PhysicalFileProvider(_projectPath),
ContentRootFileProvider = new PhysicalFileProvider(_contentRoot),
ContentRootPath = _contentRoot,
};
var diagnosticSource = new DiagnosticListener("Microsoft.AspNetCore");
services
.AddSingleton<IHostingEnvironment>(hostingEnvironment)
.AddSingleton<DiagnosticSource>(diagnosticSource)
.AddLogging()
.AddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();
var mvcCoreBuilder = services
.AddMvcCore()
.AddRazorViewEngine();
var mvcBuilder = new MvcBuilder(mvcCoreBuilder.Services, mvcCoreBuilder.PartManager);
mvcBuilderConfiguration?.ConfigureMvc(mvcBuilder);
return mvcBuilder.Services.BuildServiceProvider();
}
}
}

View File

@ -0,0 +1,61 @@
// 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.Extensions.CommandLineUtils;
namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design.Internal
{
public class PrecompilationApplication : CommandLineApplication
{
private readonly Type _callingType;
public PrecompilationApplication(Type callingType)
{
_callingType = callingType;
Name = "razor-precompile";
FullName = "Microsoft Razor Precompilation Utility";
Description = "Precompiles Razor views.";
ShortVersionGetter = GetInformationalVersion;
HelpOption("-?|-h|--help");
OnExecute(() =>
{
ShowHelp();
return 2;
});
}
public new int Execute(params string[] args)
{
try
{
return base.Execute(args);
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.Message);
#if DEBUG
Console.Error.WriteLine(ex);
#endif
return 1;
}
}
private string GetInformationalVersion()
{
var assembly = _callingType.GetTypeInfo().Assembly;
var attributes = assembly.GetCustomAttributes(
typeof(AssemblyInformationalVersionAttribute)) as AssemblyInformationalVersionAttribute[];
var versionAttribute = attributes.Length == 0 ?
assembly.GetName().Version.ToString() :
attributes[0].InformationalVersion;
return versionAttribute;
}
}
}

View File

@ -0,0 +1,244 @@
// 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.Reflection;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.AspNetCore.Mvc.Razor.Internal;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Text;
using Microsoft.Extensions.CommandLineUtils;
using Microsoft.Extensions.FileProviders;
namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design.Internal
{
public class PrecompileRunCommand
{
public static readonly string ApplicationNameTemplate = "--applicationName";
public static readonly string OutputPathTemplate = "--output-path";
private static readonly ParallelOptions ParalellOptions = new ParallelOptions
{
MaxDegreeOfParallelism = 4
};
private CommandOption OutputPathOption { get; set; }
private CommandOption ApplicationNameOption { get; set; }
private MvcServiceProvider MvcServiceProvider { get; set; }
private CommonOptions Options { get; } = new CommonOptions();
private StrongNameOptions StrongNameOptions { get; } = new StrongNameOptions();
private string ProjectPath { get; set; }
public void Configure(CommandLineApplication app)
{
Options.Configure(app);
StrongNameOptions.Configure(app);
OutputPathOption = app.Option(
OutputPathTemplate,
"Path to the emit the precompiled assembly to.",
CommandOptionType.SingleValue);
ApplicationNameOption = app.Option(
ApplicationNameTemplate,
"Name of the application to produce precompiled assembly for.",
CommandOptionType.SingleValue);
app.OnExecute(() => Execute());
}
private int Execute()
{
ParseArguments();
MvcServiceProvider = new MvcServiceProvider(
ProjectPath,
ApplicationNameOption.Value(),
Options.ContentRootOption.Value(),
Options.ConfigureCompilationType.Value());
Console.WriteLine("Running Razor view precompilation.");
var stopWatch = Stopwatch.StartNew();
var results = GenerateCode();
var success = true;
foreach (var result in results)
{
if (!result.GeneratorResults.Success)
{
success = false;
foreach (var error in result.GeneratorResults.ParserErrors)
{
Console.Error.WriteLine($"{error.Location.FilePath} ({error.Location.LineIndex}): {error.Message}");
}
}
}
if (!success)
{
return 1;
}
var precompileAssemblyName = $"{ApplicationNameOption.Value()}{AssemblyPart.PrecompiledViewsAssemblySuffix}";
var compilation = CompileViews(results, precompileAssemblyName);
var assemblyPath = Path.Combine(OutputPathOption.Value(), precompileAssemblyName + ".dll");
var emitResult = EmitAssembly(compilation, assemblyPath);
if (!emitResult.Success)
{
foreach (var diagnostic in emitResult.Diagnostics)
{
Console.Error.WriteLine(CSharpDiagnosticFormatter.Instance.Format(diagnostic));
}
return 1;
}
stopWatch.Stop();
Console.WriteLine($"Precompiled views emitted to {assemblyPath}.");
Console.WriteLine($"Successfully compiled {results.Length} Razor views in {stopWatch.ElapsedMilliseconds}ms.");
return 0;
}
private EmitResult EmitAssembly(CSharpCompilation compilation, string assemblyPath)
{
Directory.CreateDirectory(Path.GetDirectoryName(assemblyPath));
EmitResult emitResult;
using (var assemblyStream = File.OpenWrite(assemblyPath))
{
using (var pdbStream = File.OpenWrite(Path.ChangeExtension(assemblyPath, ".pdb")))
{
emitResult = compilation.Emit(
assemblyStream,
pdbStream,
options: MvcServiceProvider.Compiler.EmitOptions);
}
}
return emitResult;
}
private CSharpCompilation CompileViews(ViewCompilationInfo[] results, string assemblyname)
{
var compiler = MvcServiceProvider.Compiler;
var compilation = compiler.CreateCompilation(assemblyname);
var syntaxTrees = new SyntaxTree[results.Length];
Parallel.For(0, results.Length, ParalellOptions, i =>
{
var result = results[i];
var sourceText = SourceText.From(result.GeneratorResults.GeneratedCode, Encoding.UTF8);
var fileInfo = result.RelativeFileInfo;
var syntaxTree = compiler.CreateSyntaxTree(sourceText)
.WithFilePath(fileInfo.FileInfo.PhysicalPath ?? fileInfo.RelativePath);
syntaxTrees[i] = syntaxTree;
});
compilation = compilation.AddSyntaxTrees(syntaxTrees);
Parallel.For(0, results.Length, ParalellOptions, i =>
{
results[i].TypeName = ReadTypeInfo(compilation, syntaxTrees[i]);
});
// Post process the compilation - run ExpressionRewritter and any user specified callbacks.
compilation = ExpressionRewriter.Rewrite(compilation);
var compilationContext = new RoslynCompilationContext(compilation);
MvcServiceProvider.ViewEngineOptions.CompilationCallback(compilationContext);
compilation = compilationContext.Compilation;
var codeGenerator = new ViewInfoContainerCodeGenerator(compiler, compilation);
codeGenerator.AddViewFactory(results);
var assemblyName = new AssemblyName(ApplicationNameOption.Value());
assemblyName = Assembly.Load(assemblyName).GetName();
codeGenerator.AddAssemblyMetadata(assemblyName, StrongNameOptions);
return codeGenerator.Compilation;
}
private void ParseArguments()
{
ProjectPath = Options.ProjectArgument.Value;
if (string.IsNullOrEmpty(ProjectPath))
{
throw new ArgumentException("Project path not specified.");
}
if (!OutputPathOption.HasValue())
{
throw new ArgumentException($"Option {OutputPathTemplate} does not specify a value.");
}
if (!ApplicationNameOption.HasValue())
{
throw new ArgumentException($"Option {ApplicationNameTemplate} does not specify a value.");
}
}
private ViewCompilationInfo[] GenerateCode()
{
var files = new List<RelativeFileInfo>();
GetRazorFiles(MvcServiceProvider.FileProvider, files, root: string.Empty);
var results = new ViewCompilationInfo[files.Count];
Parallel.For(0, results.Length, ParalellOptions, i =>
{
var fileInfo = files[i];
using (var fileStream = fileInfo.FileInfo.CreateReadStream())
{
var result = MvcServiceProvider.Host.GenerateCode(fileInfo.RelativePath, fileStream);
results[i] = new ViewCompilationInfo(fileInfo, result);
}
});
return results;
}
private static void GetRazorFiles(IFileProvider fileProvider, List<RelativeFileInfo> razorFiles, string root)
{
foreach (var fileInfo in fileProvider.GetDirectoryContents(root))
{
var relativePath = Path.Combine(root, fileInfo.Name);
if (fileInfo.IsDirectory)
{
GetRazorFiles(fileProvider, razorFiles, relativePath);
}
else if (fileInfo.Name.EndsWith(".cshtml", StringComparison.OrdinalIgnoreCase))
{
razorFiles.Add(new RelativeFileInfo(fileInfo, relativePath));
}
}
}
private string ReadTypeInfo(CSharpCompilation compilation, SyntaxTree syntaxTree)
{
var semanticModel = compilation.GetSemanticModel(syntaxTree, ignoreAccessibility: true);
var classDeclarations = syntaxTree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>();
foreach (var declaration in classDeclarations)
{
var typeSymbol = semanticModel.GetDeclaredSymbol(declaration);
if (typeSymbol.ContainingType == null && typeSymbol.DeclaredAccessibility == Accessibility.Public)
{
return typeSymbol.ToDisplayString();
}
}
return null;
}
}
}

View File

@ -0,0 +1,88 @@
// 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.Immutable;
using System.IO;
namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design.Internal
{
// Copied from https://github.com/dotnet/cli/blob/rel/1.0.0/src/Microsoft.DotNet.ProjectModel.Workspaces/SnkUtils.cs
public static class SnkUtils
{
const byte PUBLICKEYBLOB = 0x06;
const byte PRIVATEKEYBLOB = 0x07;
private const uint CALG_RSA_SIGN = 0x00002400;
private const uint CALG_SHA = 0x00008004;
private const uint RSA1 = 0x31415352; //"RSA1" publickeyblob
private const uint RSA2 = 0x32415352; //"RSA2" privatekeyblob
private const int VersionOffset = 1;
private const int ModulusLengthOffset = 12;
private const int ExponentOffset = 16;
private const int MagicPrivateKeyOffset = 8;
private const int MagicPublicKeyOffset = 20;
public static ImmutableArray<byte> ExtractPublicKey(byte[] snk)
{
ValidateBlob(snk);
if (snk[0] != PRIVATEKEYBLOB)
{
return ImmutableArray.Create(snk);
}
var version = snk[VersionOffset];
int modulusBitLength = ReadInt32(snk, ModulusLengthOffset);
uint exponent = (uint)ReadInt32(snk, ExponentOffset);
var modulus = new byte[modulusBitLength >> 3];
Array.Copy(snk, 20, modulus, 0, modulus.Length);
return CreatePublicKey(version, exponent, modulus);
}
private static void ValidateBlob(byte[] snk)
{
// 160 - the size of public key
if (snk.Length >= 160)
{
if (snk[0] == PRIVATEKEYBLOB && ReadInt32(snk, MagicPrivateKeyOffset) == RSA2 || // valid private key
snk[12] == PUBLICKEYBLOB && ReadInt32(snk, MagicPublicKeyOffset) == RSA1) // valid public key
{
return;
}
}
throw new InvalidOperationException("Invalid key file.");
}
private static int ReadInt32(byte[] array, int index)
{
return array[index] | array[index + 1] << 8 | array[index + 2] << 16 | array[index + 3] << 24;
}
private static ImmutableArray<byte> CreatePublicKey(byte version, uint exponent, byte[] modulus)
{
using (var ms = new MemoryStream(160))
using (var binaryWriter = new BinaryWriter(ms))
{
binaryWriter.Write(CALG_RSA_SIGN);
binaryWriter.Write(CALG_SHA);
// total size of the rest of the blob (20 - size of RSAPUBKEY)
binaryWriter.Write(modulus.Length + 20);
binaryWriter.Write(PUBLICKEYBLOB);
binaryWriter.Write(version);
binaryWriter.Write((ushort)0x00000000); // reserved
binaryWriter.Write(CALG_RSA_SIGN);
binaryWriter.Write(RSA1);
binaryWriter.Write(modulus.Length << 3);
binaryWriter.Write(exponent);
binaryWriter.Write(modulus);
return ImmutableArray.Create(ms.ToArray());
}
}
}
}

View File

@ -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 Microsoft.Extensions.CommandLineUtils;
namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design.Internal
{
public class StrongNameOptions
{
public static readonly string StrongNameKeyPath = "--key-file";
public static readonly string DelaySignTemplate = "--delay-sign";
public static readonly string PublicSignTemplate = "--public-sign";
public CommandOption KeyFileOption { get; set; }
public CommandOption DelaySignOption { get; private set; }
public CommandOption PublicSignOption { get; private set; }
public void Configure(CommandLineApplication app)
{
KeyFileOption = app.Option(
StrongNameKeyPath,
"Strong name key path",
CommandOptionType.SingleValue);
DelaySignOption = app.Option(
DelaySignTemplate,
"Determines if the precompiled view assembly is to be delay signed.",
CommandOptionType.NoValue);
PublicSignOption = app.Option(
PublicSignTemplate,
"Determines if the precompiled view assembly is to be public signed.",
CommandOptionType.NoValue);
}
public string KeyFile => KeyFileOption.Value();
public bool DelaySign => DelaySignOption.HasValue();
public bool PublicSign => PublicSignOption.HasValue();
}
}

View File

@ -0,0 +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 Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.AspNetCore.Razor.CodeGenerators;
namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design.Internal
{
public class ViewCompilationInfo
{
public ViewCompilationInfo(
RelativeFileInfo relativeFileInfo,
GeneratorResults generatorResults)
{
RelativeFileInfo = relativeFileInfo;
GeneratorResults = generatorResults;
}
public RelativeFileInfo RelativeFileInfo { get; }
public GeneratorResults GeneratorResults { get; }
public string TypeName { get; set; }
}
}

View File

@ -0,0 +1,85 @@
// 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.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Razor.Internal;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design.Internal
{
public class ViewInfoContainerCodeGenerator
{
public ViewInfoContainerCodeGenerator(
CSharpCompiler compiler,
CSharpCompilation compilation)
{
Compiler = compiler;
Compilation = compilation;
}
public CSharpCompiler Compiler { get; }
public CSharpCompilation Compilation { get; private set; }
public void AddViewFactory(IList<ViewCompilationInfo> result)
{
var precompiledViewsArray = new StringBuilder();
foreach (var item in result)
{
var path = item.RelativeFileInfo.RelativePath;
precompiledViewsArray.AppendLine(
$"new global::{typeof(ViewInfo).FullName}(@\"{path}\", typeof({item.TypeName})),");
}
var factoryContent = $@"
namespace {AssemblyPart.ViewInfoContainerNamespace}
{{
public class {AssemblyPart.ViewInfoContainerTypeName} : global::{typeof(ViewInfoContainer).FullName}
{{
public {AssemblyPart.ViewInfoContainerTypeName}() : base(new[]
{{
{precompiledViewsArray}
}})
{{
}}
}}
}}";
var syntaxTree = Compiler.CreateSyntaxTree(SourceText.From(factoryContent));
Compilation = Compilation.AddSyntaxTrees(syntaxTree);
}
public void AddAssemblyMetadata(
AssemblyName applicationAssemblyName,
StrongNameOptions strongNameOptions)
{
if (!string.IsNullOrEmpty(strongNameOptions.KeyFile))
{
var updatedOptions = Compilation.Options.WithStrongNameProvider(new DesktopStrongNameProvider());
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || strongNameOptions.PublicSign)
{
updatedOptions = updatedOptions.WithCryptoPublicKey(
SnkUtils.ExtractPublicKey(File.ReadAllBytes(strongNameOptions.KeyFile)));
}
else
{
updatedOptions = updatedOptions.WithCryptoKeyFile(strongNameOptions.KeyFile)
.WithDelaySign(strongNameOptions.DelaySign);
}
Compilation = Compilation.WithOptions(updatedOptions);
}
var assemblyVersionContent = $"[assembly:{typeof(AssemblyVersionAttribute).FullName}(\"{applicationAssemblyName.Version}\")]";
var syntaxTree = Compiler.CreateSyntaxTree(SourceText.From(assemblyVersionContent));
Compilation = Compilation.AddSyntaxTrees(syntaxTree);
}
}
}

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.25420" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25420</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>4339fc9b-aec6-442a-b413-a41555ed76c7</ProjectGuid>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -0,0 +1,66 @@
// 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.Reflection;
using Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design.Internal;
namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design
{
public class Program
{
private readonly static Type ProgramType = typeof(Program);
public static int Main(string[] args)
{
#if DEBUG
DebugHelper.HandleDebugSwitch(ref args);
#endif
EnsureValidDispatchRecipient(ref args);
var app = new PrecompilationApplication(ProgramType);
new PrecompileRunCommand().Configure(app);
return app.Execute(args);
}
private static void EnsureValidDispatchRecipient(ref string[] args)
{
const string DispatcherVersionArgumentName = "--dispatcher-version";
var dispatcherArgumentIndex = Array.FindIndex(
args,
(value) => string.Equals(value, DispatcherVersionArgumentName, StringComparison.OrdinalIgnoreCase));
if (dispatcherArgumentIndex < 0)
{
return;
}
var dispatcherArgumentValueIndex = dispatcherArgumentIndex + 1;
if (dispatcherArgumentValueIndex < args.Length)
{
var dispatcherVersion = args[dispatcherArgumentValueIndex];
var thisAssembly = ProgramType.GetTypeInfo().Assembly;
var version = thisAssembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()
?.InformationalVersion
?? thisAssembly.GetName().Version.ToString();
if (string.Equals(dispatcherVersion, version, StringComparison.Ordinal))
{
// Remove dispatcher arguments from
var preDispatcherArgument = args.Take(dispatcherArgumentIndex);
var postDispatcherArgument = args.Skip(dispatcherArgumentIndex + 2);
var newProgramArguments = preDispatcherArgument.Concat(postDispatcherArgument);
args = newProgramArguments.ToArray();
return;
}
}
// Could not validate the dispatcher version.
throw new InvalidOperationException("Could not invoke tool");
}
}
}

View File

@ -0,0 +1,11 @@
// 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 System.Resources;
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: NeutralResourcesLanguage("en-us")]
[assembly: AssemblyCompany("Microsoft Corporation.")]
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyProduct("Microsoft ASP.NET Core")]

View File

@ -0,0 +1,41 @@
{
"version": "1.0.0-*",
"description": "Razor precompilation",
"packOptions": {
"repository": {
"type": "git",
"url": "git://github.com/AspNet/Mvc"
},
"tags": [
"cshtml",
"razor",
"precompilation",
"aspnetcore"
]
},
"buildOptions": {
"keyFile": "../../tools/Key.snk",
"warningsAsErrors": true,
"emitEntryPoint": true,
"nowarn": [
"CS1591"
],
"xmlDoc": true
},
"dependencies": {
"Microsoft.AspNetCore.Hosting": "1.1.0-*",
"Microsoft.AspNetCore.Mvc.Razor": "1.1.0-*",
"Microsoft.Extensions.CommandLineUtils": "1.1.0-*"
},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0-*"
}
}
},
"net451": {}
}
}

View File

@ -0,0 +1,188 @@
// 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.Reflection;
using Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design.Internal;
using Microsoft.DotNet.InternalAbstractions;
using Microsoft.DotNet.ProjectModel;
using Microsoft.Extensions.CommandLineUtils;
using Microsoft.Extensions.Internal;
using NuGet.Frameworks;
namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Internal
{
public class PrecompileDispatchCommand
{
private CommonOptions Options { get; } = new CommonOptions();
private CommandOption FrameworkOption { get; set; }
private CommandOption ConfigurationOption { get; set; }
private CommandOption OutputPathOption { get; set; }
private NuGetFramework TargetFramework { get; set; }
private CommandOption BuildBasePathOption { get; set; }
private string ProjectPath { get; set; }
private string Configuration { get; set; }
private string OutputPath { get; set; }
public void Configure(CommandLineApplication app)
{
Options.Configure(app);
FrameworkOption = app.Option(
"-f|--framework",
"Target Framework",
CommandOptionType.SingleValue);
ConfigurationOption = app.Option(
"-c|--configuration",
"Configuration",
CommandOptionType.SingleValue);
OutputPathOption = app.Option(
"-o|--output-path",
"Published path of the application.",
CommandOptionType.SingleValue);
app.OnExecute(() => Execute());
}
private int Execute()
{
ParseArguments();
var runtimeContext = GetRuntimeContext();
var outputPaths = runtimeContext.GetOutputPaths(Configuration);
var applicationName = Path.GetFileNameWithoutExtension(outputPaths.CompilationFiles.Assembly);
var dispatchArgs = new List<string>
{
ProjectPath,
PrecompileRunCommand.ApplicationNameTemplate,
applicationName,
PrecompileRunCommand.OutputPathTemplate,
OutputPath,
CommonOptions.ContentRootTemplate,
Options.ContentRootOption.Value() ?? Directory.GetCurrentDirectory(),
};
if (Options.ConfigureCompilationType.HasValue())
{
dispatchArgs.Add(CommonOptions.ConfigureCompilationTypeTemplate);
dispatchArgs.Add(Options.ConfigureCompilationType.Value());
}
var compilerOptions = runtimeContext.ProjectFile.GetCompilerOptions(TargetFramework, Configuration);
if (!string.IsNullOrEmpty(compilerOptions.KeyFile))
{
dispatchArgs.Add(StrongNameOptions.StrongNameKeyPath);
var keyFilePath = Path.GetFullPath(Path.Combine(runtimeContext.ProjectDirectory, compilerOptions.KeyFile));
dispatchArgs.Add(keyFilePath);
if (compilerOptions.DelaySign ?? false)
{
dispatchArgs.Add(StrongNameOptions.DelaySignTemplate);
}
if (compilerOptions.PublicSign ?? false)
{
dispatchArgs.Add(StrongNameOptions.PublicSignTemplate);
}
}
#if DEBUG
var commandLineArgs = Environment.GetCommandLineArgs();
if (commandLineArgs.Length > 0 && commandLineArgs[0] == "--debug")
{
dispatchArgs.Insert(0, commandLineArgs[0]);
}
#endif
var toolName = typeof(Design.Program).GetTypeInfo().Assembly.GetName().Name;
var dispatchCommand = DotnetToolDispatcher.CreateDispatchCommand(
dispatchArgs,
TargetFramework,
Configuration,
outputPath: outputPaths.RuntimeOutputPath,
buildBasePath: null,
projectDirectory: ProjectPath,
toolName: toolName);
var commandExitCode = dispatchCommand
.ForwardStdErr(Console.Error)
.ForwardStdOut(Console.Out)
.Execute()
.ExitCode;
return commandExitCode;
}
private void ParseArguments()
{
ProjectPath = GetProjectPath();
Configuration = ConfigurationOption.Value() ?? DotNet.Cli.Utils.Constants.DefaultConfiguration;
if (!FrameworkOption.HasValue())
{
throw new Exception($"Option {FrameworkOption.Template} does not have a value.");
}
TargetFramework = NuGetFramework.Parse(FrameworkOption.Value());
if (!OutputPathOption.HasValue())
{
throw new Exception($"Option {OutputPathOption.Template} does not have a value.");
}
OutputPath = OutputPathOption.Value();
}
private string GetProjectPath()
{
string projectPath;
if (!string.IsNullOrEmpty(Options.ProjectArgument.Value))
{
projectPath = Path.GetFullPath(Options.ProjectArgument.Value);
if (string.Equals(Path.GetFileName(ProjectPath), "project.json", StringComparison.OrdinalIgnoreCase))
{
projectPath = Path.GetDirectoryName(ProjectPath);
}
if (!Directory.Exists(projectPath))
{
throw new InvalidOperationException($"Could not find directory {projectPath}.");
}
}
else
{
projectPath = Directory.GetCurrentDirectory();
}
return projectPath;
}
private ProjectContext GetRuntimeContext()
{
var workspace = new BuildWorkspace(ProjectReaderSettings.ReadFromEnvironment());
var projectContext = workspace.GetProjectContext(ProjectPath, TargetFramework);
if (projectContext == null)
{
Debug.Assert(FrameworkOption.HasValue());
throw new InvalidOperationException($"Project '{ProjectPath}' does not support framework: {FrameworkOption.Value()}");
}
var runtimeContext = workspace.GetRuntimeContext(
projectContext,
RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers());
return runtimeContext;
}
}
}

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.25420" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25420</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>f8bf7d95-0633-407f-bb0b-02563f13c068</ProjectGuid>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -0,0 +1,22 @@
// 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.Mvc.Razor.Precompilation.Design.Internal;
using Microsoft.AspNetCore.Mvc.Razor.Precompilation.Internal;
namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Tools
{
public class Program
{
public static int Main(string[] args)
{
#if DEBUG
DebugHelper.HandleDebugSwitch(ref args);
#endif
var app = new PrecompilationApplication(typeof(Program));
new PrecompileDispatchCommand().Configure(app);
return app.Execute(args);
}
}
}

View File

@ -0,0 +1,11 @@
// 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 System.Resources;
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: NeutralResourcesLanguage("en-us")]
[assembly: AssemblyCompany("Microsoft Corporation.")]
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyProduct("Microsoft ASP.NET Core")]

View File

@ -0,0 +1,49 @@
{
"version": "1.0.0-*",
"description": "Razor precompilation",
"packOptions": {
"repository": {
"type": "git",
"url": "git://github.com/AspNet/Mvc"
},
"tags": [
"cshtml",
"razor",
"precompilation",
"aspnetcore"
]
},
"buildOptions": {
"outputName": "dotnet-razor-precompile",
"keyFile": "../../tools/Key.snk",
"warningsAsErrors": true,
"emitEntryPoint": true,
"nowarn": [
"CS1591"
],
"xmlDoc": true
},
"dependencies": {
"Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design": { "target": "project" },
"Microsoft.DotNet.Cli.Utils": "1.0.0-*",
"Microsoft.Extensions.CommandLineUtils": "1.1.0-*",
"Microsoft.Extensions.DotnetToolDispatcher.Sources": {
"type": "build",
"version": "1.1.0-*"
}
},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.DotNet.ProjectModel.Loader": "1.0.0-*",
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0-*"
},
"System.Runtime.Serialization.Primitives": "4.1.1-*"
}
},
"net451": {}
}
}

View File

@ -0,0 +1,98 @@
// 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.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Tests
{
public class ApplicationWithConfigureMvcTest
: IClassFixture<ApplicationWithConfigureMvcTest.ApplicationWithConfigureMvcFixture>
{
public ApplicationWithConfigureMvcTest(ApplicationWithConfigureMvcFixture fixture)
{
Fixture = fixture;
}
public ApplicationTestFixture Fixture { get; }
public static IEnumerable<object[]> ApplicationWithTagHelpersData
{
get
{
var runtimeFlavors = new[]
{
RuntimeFlavor.Clr,
RuntimeFlavor.CoreClr,
};
var urls = new[]
{
"Index",
"ViewWithPreprocessor",
};
return Enumerable.Zip(urls, runtimeFlavors, (a, b) => new object[] { a, b });
}
}
[Theory]
[InlineData(RuntimeFlavor.Clr)]
[InlineData(RuntimeFlavor.CoreClr)]
public async Task Precompilation_RunsConfiguredCompilationCallbacks(RuntimeFlavor flavor)
{
// Arrange
using (var deployer = Fixture.CreateDeployment(flavor))
{
var deploymentResult = deployer.Deploy();
var httpClient = new HttpClient()
{
BaseAddress = new Uri(deploymentResult.ApplicationBaseUri)
};
// Act
var response = await httpClient.GetStringAsync("");
// Assert
TestEmbeddedResource.AssertContent("ApplicationWithConfigureMvc.Home.Index.txt", response);
}
}
[Theory]
[InlineData(RuntimeFlavor.Clr)]
[InlineData(RuntimeFlavor.CoreClr)]
public async Task Precompilation_UsesConfiguredParseOptions(RuntimeFlavor flavor)
{
// Arrange
using (var deployer = Fixture.CreateDeployment(flavor))
{
var deploymentResult = deployer.Deploy();
var httpClient = new HttpClient()
{
BaseAddress = new Uri(deploymentResult.ApplicationBaseUri)
};
// Act
var response = await httpClient.GetStringAsync("Home/ViewWithPreprocessor");
// Assert
TestEmbeddedResource.AssertContent(
"ApplicationWithConfigureMvc.Home.ViewWithPreprocessor.txt",
response);
}
}
public class ApplicationWithConfigureMvcFixture : ApplicationTestFixture
{
public ApplicationWithConfigureMvcFixture()
: base("ApplicationWithConfigureMvc")
{
}
}
}
}

View File

@ -0,0 +1,80 @@
// 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.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation
{
public class TagHelperTest : IClassFixture<TagHelperTest.ApplicationWithTagHelpersFixture>
{
public TagHelperTest(ApplicationWithTagHelpersFixture fixture)
{
Fixture = fixture;
}
public ApplicationTestFixture Fixture { get; }
public static IEnumerable<object[]> ApplicationWithTagHelpersData
{
get
{
var runtimeFlavors = new[]
{
RuntimeFlavor.Clr,
RuntimeFlavor.CoreClr,
};
var urls = new[]
{
"ClassLibraryTagHelper",
"LocalTagHelper",
"NuGetPackageTagHelper",
};
return Enumerable.Zip(urls, runtimeFlavors, (a, b) => new object[] { a, b });
}
}
[Theory]
[MemberData(nameof(ApplicationWithTagHelpersData))]
public async Task Precompilation_WorksForViewsThatUseTagHelpers(string url, RuntimeFlavor flavor)
{
// Arrange
using (var deployer = Fixture.CreateDeployment(flavor))
{
var deploymentResult = deployer.Deploy();
var httpClient = new HttpClient()
{
BaseAddress = new Uri(deploymentResult.ApplicationBaseUri)
};
// Act
var response = await httpClient.GetStringAsync($"Home/{url}");
// Assert
TestEmbeddedResource.AssertContent($"ApplicationWithTagHelpers.Home.{url}.txt", response);
}
}
public class ApplicationWithTagHelpersFixture : ApplicationTestFixture
{
public ApplicationWithTagHelpersFixture()
: base("ApplicationWithTagHelpers")
{
}
protected override void Restore()
{
RestoreProject(Path.GetFullPath(Path.Combine(ApplicationPath, "..", "ClassLibraryTagHelper")));
base.Restore();
}
}
}
}

View File

@ -0,0 +1,40 @@
// 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.Extensions.PlatformAbstractions;
namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation
{
public static class ApplicationPaths
{
private const string SolutionName = "MvcPrecompilation.sln";
public static string SolutionDirectory { get; } = GetSolutionDirectory();
public static string ArtifactPackagesDirectory => Path.Combine(SolutionDirectory, "artifacts", "build");
public static string GetTestAppDirectory(string appName) =>
Path.Combine(SolutionDirectory, "testapps", appName);
private static string GetSolutionDirectory()
{
var applicationBasePath = PlatformServices.Default.Application.ApplicationBasePath;
var directoryInfo = new DirectoryInfo(applicationBasePath);
do
{
var solutionFileInfo = new FileInfo(Path.Combine(directoryInfo.FullName, SolutionName));
if (solutionFileInfo.Exists)
{
return directoryInfo.FullName;
}
directoryInfo = directoryInfo.Parent;
} while (directoryInfo.Parent != null);
throw new InvalidOperationException($"Solution directory could not be found for {applicationBasePath}.");
}
}
}

View File

@ -0,0 +1,144 @@
// 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.Runtime.InteropServices;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.Extensions.Logging;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation
{
public abstract class ApplicationTestFixture : IDisposable
{
public const string NuGetPackagesEnvironmentKey = "NUGET_PACKAGES";
private readonly string _oldRestoreDirectory;
private bool _isRestored;
protected ApplicationTestFixture(string applicationName)
{
ApplicationName = applicationName;
_oldRestoreDirectory = Environment.GetEnvironmentVariable(NuGetPackagesEnvironmentKey);
}
public string ApplicationName { get; }
public string ApplicationPath => ApplicationPaths.GetTestAppDirectory(ApplicationName);
public string TempRestoreDirectory { get; } = CreateTempRestoreDirectory();
public IApplicationDeployer CreateDeployment(RuntimeFlavor flavor)
{
if (!_isRestored)
{
Restore();
_isRestored = true;
}
var tempRestoreDirectoryEnvironment = new KeyValuePair<string, string>(
NuGetPackagesEnvironmentKey,
TempRestoreDirectory);
var deploymentParameters = new DeploymentParameters(
ApplicationPath,
ServerType.Kestrel,
flavor,
RuntimeArchitecture.x64)
{
PublishApplicationBeforeDeployment = true,
TargetFramework = flavor == RuntimeFlavor.Clr ? "net451" : "netcoreapp1.0",
Configuration = "Release",
EnvironmentVariables =
{
tempRestoreDirectoryEnvironment
},
PublishEnvironmentVariables =
{
tempRestoreDirectoryEnvironment
},
};
var logger = new LoggerFactory()
.AddConsole()
.CreateLogger($"{ApplicationName}:{flavor}");
return ApplicationDeployerFactory.Create(deploymentParameters, logger);
}
protected virtual void Restore()
{
RestoreProject(ApplicationPath);
}
public void Dispose()
{
try
{
Directory.Delete(TempRestoreDirectory, recursive: true);
}
catch (IOException)
{
// Ignore delete failures.
}
}
protected void RestoreProject(string applicationDirectory)
{
var packagesDirectory = GetNuGetPackagesDirectory();
var args = new[]
{
Path.Combine(applicationDirectory, "project.json"),
"-s",
packagesDirectory,
"-s",
ApplicationPaths.ArtifactPackagesDirectory,
"--packages",
TempRestoreDirectory,
};
var commandResult = Command
.CreateDotNet("restore", args)
.ForwardStdErr(Console.Error)
.ForwardStdOut(Console.Out)
.Execute();
Assert.True(commandResult.ExitCode == 0,
string.Join(Environment.NewLine,
$"dotnet {commandResult.StartInfo.Arguments} exited with {commandResult.ExitCode}.",
commandResult.StdOut,
commandResult.StdErr));
Console.WriteLine(commandResult.StdOut);
}
private static string CreateTempRestoreDirectory()
{
var path = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
return Directory.CreateDirectory(path).FullName;
}
private static string GetNuGetPackagesDirectory()
{
var nugetFeed = Environment.GetEnvironmentVariable(NuGetPackagesEnvironmentKey);
if (!string.IsNullOrEmpty(nugetFeed))
{
return nugetFeed;
}
string basePath;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
basePath = Environment.GetEnvironmentVariable("USERPROFILE");
}
else
{
basePath = Environment.GetEnvironmentVariable("HOME");
}
return Path.Combine(basePath, ".nuget", "packages");
}
}
}

View File

@ -0,0 +1,59 @@
// 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.Reflection;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation
{
public static class TestEmbeddedResource
{
private static readonly object _writeLock = new object();
private static readonly string ProjectName = typeof(TestEmbeddedResource).GetTypeInfo().Assembly.GetName().Name;
public static void AssertContent(string resourceFile, string actual)
{
var expected = GetResourceContent(resourceFile);
#if GENERATE_BASELINES
// Normalize line endings to '\r\n' for comparison. This removes Environment.NewLine from the equation. Not
// worth updating files just because we generate baselines on a different system.
var normalizedContent = actual.Replace("\r", "").Replace("\n", "\r\n");
if (!string.Equals(expected, normalizedContent, System.StringComparison.Ordinal))
{
var solutionRoot = ApplicationPaths.SolutionDirectory;
var projectName = typeof(TestEmbeddedResource).GetTypeInfo().Assembly.GetName().Name;
var fullPath = Path.Combine(solutionRoot, "test", ProjectName, "Resources", resourceFile);
lock (_writeLock)
{
// Write content to the file, creating it if necessary.
File.WriteAllText(fullPath, actual);
}
}
#else
Assert.Equal(expected, actual, ignoreLineEndingDifferences: true);
#endif
}
private static string GetResourceContent(string resourceFile)
{
resourceFile = $"{ProjectName}.Resources.{resourceFile}";
var assembly = typeof(TestEmbeddedResource).GetTypeInfo().Assembly;
var resourceStream = assembly.GetManifestResourceStream(resourceFile);
if (resourceStream == null)
{
return null;
}
using (var streamReader = new StreamReader(resourceStream))
{
// Normalize line endings to '\r\n' (CRLF). This removes core.autocrlf, core.eol, core.safecrlf, and
// .gitattributes from the equation and treats "\r\n" and "\n" as equivalent. Does not handle
// some line endings like "\r" but otherwise ensures checksums and line mappings are consistent.
return streamReader.ReadToEnd().Replace("\r", "").Replace("\n", "\r\n");
}
}
}
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>46c9a4b2-8b1c-451b-b670-c194901d66ac</ProjectGuid>
<RootNamespace>Microsoft.AspNetCore.Mvc.Razor.Precompilation.Tests</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -0,0 +1,3 @@
using Xunit;
[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)]

View File

@ -0,0 +1,2 @@
AspNetCore.Views_Home_Index_cshtml, ApplicationWithConfigureMvc.PrecompiledViews, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
<br />Hello world!

View File

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<title> - ApplicationWithTagHelpers</title>
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/css/bootstrap.min.css" />
<meta name="x-stylesheet-fallback-test" content="" class="sr-only" /><script>!function(a,b,c,d){var e,f=document,g=f.getElementsByTagName("SCRIPT"),h=g[g.length-1].previousElementSibling,i=f.defaultView&&f.defaultView.getComputedStyle?f.defaultView.getComputedStyle(h):h.currentStyle;if(i&&i[a]!==b)for(e=0;e<c.length;e++)f.write('<link href="'+c[e]+'" '+d+"/>")}("position","absolute",["\/lib\/bootstrap\/dist\/css\/bootstrap.min.css"], "rel=\u0022stylesheet\u0022 ");</script>
</head>
<body>
<div class="container body-content">
AspNetCore.Views_Home_ClassLibraryTagHelper_cshtml, ApplicationWithTagHelpers.PrecompiledViews, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
<div><b>To boldy tag that no one has ever tagged before...</b></div>
<hr />
<footer>
<p>&copy; 2016 - ApplicationWithTagHelpers</p>
</footer>
</div>
AspNetCore.Views_Shared__Layout_cshtml, ApplicationWithTagHelpers.PrecompiledViews, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
</body>
</html>

View File

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<title> - ApplicationWithTagHelpers</title>
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/css/bootstrap.min.css" />
<meta name="x-stylesheet-fallback-test" content="" class="sr-only" /><script>!function(a,b,c,d){var e,f=document,g=f.getElementsByTagName("SCRIPT"),h=g[g.length-1].previousElementSibling,i=f.defaultView&&f.defaultView.getComputedStyle?f.defaultView.getComputedStyle(h):h.currentStyle;if(i&&i[a]!==b)for(e=0;e<c.length;e++)f.write('<link href="'+c[e]+'" '+d+"/>")}("position","absolute",["\/lib\/bootstrap\/dist\/css\/bootstrap.min.css"], "rel=\u0022stylesheet\u0022 ");</script>
</head>
<body>
<div class="container body-content">
AspNetCore.Views_Home_LocalTagHelper_cshtml, ApplicationWithTagHelpers.PrecompiledViews, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
<test href="/Home/About">TestTagHelper content.</test>
<hr />
<footer>
<p>&copy; 2016 - ApplicationWithTagHelpers</p>
</footer>
</div>
AspNetCore.Views_Shared__Layout_cshtml, ApplicationWithTagHelpers.PrecompiledViews, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
</body>
</html>

View File

@ -0,0 +1,165 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Home Page - SimpleApp</title>
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/css/bootstrap.min.css" />
<meta name="x-stylesheet-fallback-test" content="" class="sr-only" /><script>!function(a,b,c,d){var e,f=document,g=f.getElementsByTagName("SCRIPT"),h=g[g.length-1].previousElementSibling,i=f.defaultView&&f.defaultView.getComputedStyle?f.defaultView.getComputedStyle(h):h.currentStyle;if(i&&i[a]!==b)for(e=0;e<c.length;e++)f.write('<link href="'+c[e]+'" '+d+"/>")}("position","absolute",["\/lib\/bootstrap\/dist\/css\/bootstrap.min.css"], "rel=\u0022stylesheet\u0022 ");</script>
<link rel="stylesheet" href="/css/site.min.css" />
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">SimpleApp</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
<li><a href="/Home/About">About</a></li>
<li><a href="/Home/Contact">Contact</a></li>
</ul>
</div>
</div>
</div>
<div class="container body-content">
AspNetCore.Views_Home_Index_cshtml, SimpleApp.PrecompiledViews, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
<div id="myCarousel" class="carousel slide" data-ride="carousel" data-interval="6000">
<ol class="carousel-indicators">
<li data-target="#myCarousel" data-slide-to="0" class="active"></li>
<li data-target="#myCarousel" data-slide-to="1"></li>
<li data-target="#myCarousel" data-slide-to="2"></li>
<li data-target="#myCarousel" data-slide-to="3"></li>
</ol>
<div class="carousel-inner" role="listbox">
<div class="item active">
<img src="/images/banner1.svg" alt="ASP.NET" class="img-responsive" />
<div class="carousel-caption" role="option">
<p>
Learn how to build ASP.NET apps that can run anywhere.
<a class="btn btn-default" href="http://go.microsoft.com/fwlink/?LinkID=525028&clcid=0x409">
Learn More
</a>
</p>
</div>
</div>
<div class="item">
<img src="/images/banner2.svg" alt="Visual Studio" class="img-responsive" />
<div class="carousel-caption" role="option">
<p>
There are powerful new features in Visual Studio for building modern web apps.
<a class="btn btn-default" href="http://go.microsoft.com/fwlink/?LinkID=525030&clcid=0x409">
Learn More
</a>
</p>
</div>
</div>
<div class="item">
<img src="/images/banner3.svg" alt="Package Management" class="img-responsive" />
<div class="carousel-caption" role="option">
<p>
Bring in libraries from NuGet, Bower, and npm, and automate tasks using Grunt or Gulp.
<a class="btn btn-default" href="http://go.microsoft.com/fwlink/?LinkID=525029&clcid=0x409">
Learn More
</a>
</p>
</div>
</div>
<div class="item">
<img src="/images/banner4.svg" alt="Microsoft Azure" class="img-responsive" />
<div class="carousel-caption" role="option">
<p>
Learn how Microsoft's Azure cloud platform allows you to build, deploy, and scale web apps.
<a class="btn btn-default" href="http://go.microsoft.com/fwlink/?LinkID=525027&clcid=0x409">
Learn More
</a>
</p>
</div>
</div>
</div>
<a class="left carousel-control" href="#myCarousel" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="right carousel-control" href="#myCarousel" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
<div class="row">
<div class="col-md-3">
<h2>Application uses</h2>
<ul>
<li>Sample pages using ASP.NET Core MVC</li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=518004">Bower</a> for managing client-side libraries</li>
<li>Theming using <a href="http://go.microsoft.com/fwlink/?LinkID=398939">Bootstrap</a></li>
</ul>
</div>
<div class="col-md-3">
<h2>How to</h2>
<ul>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=398600">Add a Controller and View</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=699562">Add an appsetting in config and access it in app.</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699315">Manage User Secrets using Secret Manager.</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699316">Use logging to log a message.</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699317">Add packages using NuGet.</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699318">Add client packages using Bower.</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699319">Target development, staging or production environment.</a></li>
</ul>
</div>
<div class="col-md-3">
<h2>Overview</h2>
<ul>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=518008">Conceptual overview of what is ASP.NET Core</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699320">Fundamentals of ASP.NET Core such as Startup and middleware.</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=398602">Working with Data</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=398603">Security</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=699321">Client side development</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=699322">Develop on different platforms</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=699323">Read more on the documentation site</a></li>
</ul>
</div>
<div class="col-md-3">
<h2>Run & Deploy</h2>
<ul>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=517851">Run your app</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=517853">Run tools such as EF migrations and more</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=398609">Publish to Microsoft Azure Web Apps</a></li>
</ul>
</div>
</div>
<hr />
<footer>
<p>&copy; 2016 - SimpleApp</p>
</footer>
</div>
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js">
</script>
<script>(window.jQuery||document.write("\u003Cscript src=\u0022\/lib\/jquery\/dist\/jquery.min.js\u0022\u003E\u003C\/script\u003E"));</script>
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/bootstrap.min.js">
</script>
<script>(window.jQuery && window.jQuery.fn && window.jQuery.fn.modal||document.write("\u003Cscript src=\u0022\/lib\/bootstrap\/dist\/js\/bootstrap.min.js\u0022\u003E\u003C\/script\u003E"));</script>
<script src="/js/site.min.js"></script>
AspNetCore.Views_Shared__Layout_cshtml, SimpleApp.PrecompiledViews, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
</body>
</html>

View File

@ -0,0 +1,51 @@
// 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.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation
{
public class SimpleAppTest : IClassFixture<SimpleAppTest.SimpleAppTestFixture>
{
public SimpleAppTest(SimpleAppTestFixture fixture)
{
Fixture = fixture;
}
public ApplicationTestFixture Fixture { get; }
[Theory]
[InlineData(RuntimeFlavor.Clr)]
[InlineData(RuntimeFlavor.CoreClr)]
public async Task Precompilation_WorksForSimpleApps(RuntimeFlavor flavor)
{
// Arrange
using (var deployer = Fixture.CreateDeployment(flavor))
{
var deploymentResult = deployer.Deploy();
var httpClient = new HttpClient()
{
BaseAddress = new Uri(deploymentResult.ApplicationBaseUri)
};
// Act
var response = await httpClient.GetStringAsync("");
// Assert
TestEmbeddedResource.AssertContent("SimpleAppTest.Home.Index.txt", response);
}
}
public class SimpleAppTestFixture : ApplicationTestFixture
{
public SimpleAppTestFixture()
: base("SimpleApp")
{
}
}
}
}

View File

@ -0,0 +1,29 @@
{
"buildOptions": {
"define": [
"GENERATE_BASELINES"
],
"embed": "Resources/*"
},
"dependencies": {
"dotnet-test-xunit": "2.2.0-*",
"Microsoft.AspNetCore.Server.IntegrationTesting": "0.2.0-*",
"Microsoft.Extensions.Logging": "1.1.0-*",
"Microsoft.Extensions.Logging.Console": "1.1.0-*",
"Microsoft.Extensions.PlatformAbstractions": "1.1.0-*",
"Microsoft.DotNet.Cli.Utils": "1.0.0-preview2-003121",
"xunit": "2.2.0-*"
},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
}
}
}
},
"testRunner": "xunit"
}

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.25420" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25420</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>e2eaeb85-91d5-478e-9ce2-964f68de20d0</ProjectGuid>
<RootNamespace>ApplicationWithConfigureMvc</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -0,0 +1,11 @@
using Microsoft.AspNetCore.Mvc;
namespace ApplicationWithConfigureStartup.Controllers
{
public class HomeController : Controller
{
public IActionResult Index() => View();
public IActionResult ViewWithPreprocessor() => View();
}
}

View File

@ -0,0 +1,26 @@
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
namespace ApplicationWithConfigureStartup
{
public class Program
{
public static void Main(string[] args)
{
var config = new ConfigurationBuilder()
.AddCommandLine(args)
.AddEnvironmentVariables(prefix: "ASPNETCORE_")
.Build();
var host = new WebHostBuilder()
.UseConfiguration(config)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.Build();
host.Run();
}
}
}

View File

@ -0,0 +1,19 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace ApplicationWithConfigureStartup
{
public class RazorRewriter : CSharpSyntaxRewriter
{
public override SyntaxNode VisitLiteralExpression(LiteralExpressionSyntax node)
{
if (node.Token.IsKind(SyntaxKind.StringLiteralToken))
{
return node.WithToken(SyntaxFactory.Literal(node.Token.ValueText.Replace("\r\n", "\r\n<br />")));
}
return node;
}
}
}

View File

@ -0,0 +1,47 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace ApplicationWithConfigureStartup
{
public class Startup : IDesignTimeMvcBuilderConfiguration
{
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
var builder = services.AddMvc();
ConfigureMvc(builder);
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
public void ConfigureMvc(IMvcBuilder builder)
{
builder.AddRazorOptions(options =>
{
options.ParseOptions = options.ParseOptions.WithPreprocessorSymbols(new[] { "TEST123" });
var callback = options.CompilationCallback;
options.CompilationCallback = context =>
{
callback(context);
foreach (var tree in context.Compilation.SyntaxTrees)
{
var rewrittenRoot = new RazorRewriter().Visit(tree.GetRoot());
var rewrittenTree = tree.WithRootAndOptions(rewrittenRoot, tree.Options);
context.Compilation = context.Compilation.ReplaceSyntaxTree(tree, rewrittenTree);
}
};
});
}
}
}

View File

@ -0,0 +1,2 @@
@GetType().AssemblyQualifiedName
Hello world!

View File

@ -0,0 +1,7 @@
@{
var message = "Hello world message";
#if TEST123
message = "Hello from Test123";
#endif
}
@message

View File

@ -0,0 +1,45 @@
{
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"dependencies": {
"Microsoft.AspNetCore.Mvc": "1.1.0-*",
"Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design": {
"version": "1.0.0-*",
"target": "package",
"type": "build"
},
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0-*",
"Microsoft.Extensions.Configuration.CommandLine": "1.1.0-*",
"Microsoft.Extensions.Logging.Console": "1.1.0-*"
},
"tools": {
"Microsoft.AspNetCore.Mvc.Razor.Precompilation.Tools": "1.0.0-*"
},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"version": "1.0.0",
"type": "platform"
}
}
},
"net451": {}
},
"publishOptions": {
"include": [
"wwwroot",
"appsettings.json",
"web.config"
]
},
"scripts": {
"postpublish": "dotnet razor-precompile --configuration %publish:Configuration% --framework %publish:TargetFramework% --output-path %publish:OutputPath% %publish:ProjectPath%"
}
}

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.25420" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25420</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>2079872f-e8f9-4db1-a340-c0d897807b86</ProjectGuid>
<RootNamespace>ApplicationWithTagHelpers</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -0,0 +1,15 @@
using Microsoft.AspNetCore.Mvc;
namespace ApplicationWithTagHelpers.Controllers
{
public class HomeController : Controller
{
public IActionResult ClassLibraryTagHelper() => View();
public IActionResult LocalTagHelper() => View();
public IActionResult NuGetPackageTagHelper() => View();
public IActionResult About() => Content("About content");
}
}

View File

@ -0,0 +1,26 @@
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
namespace ApplicationWithTagHelpers
{
public class Program
{
public static void Main(string[] args)
{
var config = new ConfigurationBuilder()
.AddCommandLine(args)
.AddEnvironmentVariables(prefix: "ASPNETCORE_")
.Build();
var host = new WebHostBuilder()
.UseConfiguration(config)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.Build();
host.Run();
}
}
}

View File

@ -0,0 +1,26 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace ApplicationWithTagHelpers
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}

View File

@ -0,0 +1,38 @@
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace ApplicationWithTagHelpers.TagHelpers
{
public class TestTagHelper : TagHelper
{
public TestTagHelper(IUrlHelperFactory urlHelperFactory)
{
UrlHelperFactory = urlHelperFactory;
}
[HtmlAttributeNotBound]
public IUrlHelperFactory UrlHelperFactory { get; }
[ViewContext]
[HtmlAttributeNotBound]
public ViewContext ViewContext { get; set; }
public string Controller { get; set; }
public string Action { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
var urlHelper = UrlHelperFactory.GetUrlHelper(ViewContext);
output.Attributes.SetAttribute("href", urlHelper.Action(new UrlActionContext
{
Controller = Controller,
Action = Action
}));
output.PreContent.SetContent($"{nameof(TestTagHelper)} content.");
}
}
}

View File

@ -0,0 +1,7 @@
@addTagHelper *, ClassLibraryTagHelper
@GetType().AssemblyQualifiedName
<div bold="bold">To boldy tag that no one has ever tagged before...</div>

View File

@ -0,0 +1,7 @@
@addTagHelper *, ApplicationWithTagHelpers
@GetType().AssemblyQualifiedName
<test controller="Home" action="About"></test>

View File

@ -0,0 +1,12 @@
@addTagHelper *, TagHelperSamples.Bootstrap
@GetType().AssemblyQualifiedName
<modal id="simpleModal"
title="Modal Title">
<modal-body>
<h4>Something happened</h4>
<p>Something happened</p>
</modal-body>
</modal>

View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<title>@ViewData["Title"] - ApplicationWithTagHelpers</title>
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
</head>
<body>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>&copy; 2016 - ApplicationWithTagHelpers</p>
</footer>
</div>
@RenderSection("scripts", required: false)
@GetType().AssemblyQualifiedName
</body>
</html>

View File

@ -0,0 +1,2 @@
@using ApplicationWithTagHelpers
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

View File

@ -0,0 +1,3 @@
@{
Layout = "_Layout";
}

View File

@ -0,0 +1,49 @@
{
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"dependencies": {
"ClassLibraryTagHelper": {
"target": "project"
},
"TagHelperSamples.Bootstrap": "1.1.1",
"Microsoft.AspNetCore.Mvc": "1.1.0-*",
"Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design": {
"version": "1.0.0-*",
"target": "package",
"type": "build"
},
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0-*",
"Microsoft.Extensions.Configuration.CommandLine": "1.1.0-*",
"Microsoft.Extensions.Logging.Console": "1.1.0-*"
},
"tools": {
"Microsoft.AspNetCore.Mvc.Razor.Precompilation.Tools": "1.0.0-*"
},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"version": "1.0.0",
"type": "platform"
}
}
},
"net451": {}
},
"publishOptions": {
"include": [
"wwwroot",
"appsettings.json",
"web.config"
]
},
"scripts": {
"postpublish": "dotnet razor-precompile --configuration %publish:Configuration% --framework %publish:TargetFramework% --output-path %publish:OutputPath% %publish:ProjectPath%"
}
}

View File

@ -0,0 +1,15 @@
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace ClassLibraryTagHelpers
{
[HtmlTargetElement(Attributes = "bold")]
public class BoldTagHelper : TagHelper
{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.Attributes.RemoveAll("bold");
output.PreContent.AppendHtml("<b>");
output.PostContent.AppendHtml("</b>");
}
}
}

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>39efa075-3673-49ab-95f3-aa5e88df6c30</ProjectGuid>
<RootNamespace>ClassLibraryTagHelpers</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -0,0 +1,9 @@
{
"dependencies": {
"Microsoft.AspNetCore.Razor.Runtime": "1.1.0-*"
},
"frameworks": {
"netstandard1.6": {},
"net451": {}
}
}

8
testapps/NuGet.config Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="AspNetVNext" value="https://www.myget.org/F/aspnetcidev/api/v3/index.json" />
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
<add key="LocalArtifacts" value="../artifacts/build" />
</packageSources>
</configuration>

View File

@ -0,0 +1,19 @@
using Microsoft.AspNetCore.Mvc;
namespace SimpleApp.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
public IActionResult About()
{
ViewData["Message"] = "Your application description page.";
return View();
}
}
}

View File

@ -0,0 +1,26 @@
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
namespace SimpleApp
{
public class Program
{
public static void Main(string[] args)
{
var config = new ConfigurationBuilder()
.AddCommandLine(args)
.AddEnvironmentVariables(prefix: "ASPNETCORE_")
.Build();
var host = new WebHostBuilder()
.UseConfiguration(config)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.Build();
host.Run();
}
}
}

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>8fa176ed-c29e-48d6-bc7a-1c3a862cb15f</ProjectGuid>
<RootNamespace>SimpleApp</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<DnxInvisibleContent Include="bower.json" />
<DnxInvisibleContent Include=".bowerrc" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DotNet.Web\Microsoft.DotNet.Web.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -0,0 +1,26 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace SimpleApp
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}

View File

@ -0,0 +1,7 @@
@{
ViewData["Title"] = "About";
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>
<p>Use this area to provide additional information.</p>

View File

@ -0,0 +1,110 @@
@{
ViewData["Title"] = "Home Page";
}
@GetType().AssemblyQualifiedName
<div id="myCarousel" class="carousel slide" data-ride="carousel" data-interval="6000">
<ol class="carousel-indicators">
<li data-target="#myCarousel" data-slide-to="0" class="active"></li>
<li data-target="#myCarousel" data-slide-to="1"></li>
<li data-target="#myCarousel" data-slide-to="2"></li>
<li data-target="#myCarousel" data-slide-to="3"></li>
</ol>
<div class="carousel-inner" role="listbox">
<div class="item active">
<img src="~/images/banner1.svg" alt="ASP.NET" class="img-responsive" />
<div class="carousel-caption" role="option">
<p>
Learn how to build ASP.NET apps that can run anywhere.
<a class="btn btn-default" href="http://go.microsoft.com/fwlink/?LinkID=525028&clcid=0x409">
Learn More
</a>
</p>
</div>
</div>
<div class="item">
<img src="~/images/banner2.svg" alt="Visual Studio" class="img-responsive" />
<div class="carousel-caption" role="option">
<p>
There are powerful new features in Visual Studio for building modern web apps.
<a class="btn btn-default" href="http://go.microsoft.com/fwlink/?LinkID=525030&clcid=0x409">
Learn More
</a>
</p>
</div>
</div>
<div class="item">
<img src="~/images/banner3.svg" alt="Package Management" class="img-responsive" />
<div class="carousel-caption" role="option">
<p>
Bring in libraries from NuGet, Bower, and npm, and automate tasks using Grunt or Gulp.
<a class="btn btn-default" href="http://go.microsoft.com/fwlink/?LinkID=525029&clcid=0x409">
Learn More
</a>
</p>
</div>
</div>
<div class="item">
<img src="~/images/banner4.svg" alt="Microsoft Azure" class="img-responsive" />
<div class="carousel-caption" role="option">
<p>
Learn how Microsoft's Azure cloud platform allows you to build, deploy, and scale web apps.
<a class="btn btn-default" href="http://go.microsoft.com/fwlink/?LinkID=525027&clcid=0x409">
Learn More
</a>
</p>
</div>
</div>
</div>
<a class="left carousel-control" href="#myCarousel" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="right carousel-control" href="#myCarousel" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
<div class="row">
<div class="col-md-3">
<h2>Application uses</h2>
<ul>
<li>Sample pages using ASP.NET Core MVC</li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=518004">Bower</a> for managing client-side libraries</li>
<li>Theming using <a href="http://go.microsoft.com/fwlink/?LinkID=398939">Bootstrap</a></li>
</ul>
</div>
<div class="col-md-3">
<h2>How to</h2>
<ul>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=398600">Add a Controller and View</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=699562">Add an appsetting in config and access it in app.</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699315">Manage User Secrets using Secret Manager.</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699316">Use logging to log a message.</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699317">Add packages using NuGet.</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699318">Add client packages using Bower.</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699319">Target development, staging or production environment.</a></li>
</ul>
</div>
<div class="col-md-3">
<h2>Overview</h2>
<ul>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=518008">Conceptual overview of what is ASP.NET Core</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699320">Fundamentals of ASP.NET Core such as Startup and middleware.</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=398602">Working with Data</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=398603">Security</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=699321">Client side development</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=699322">Develop on different platforms</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=699323">Read more on the documentation site</a></li>
</ul>
</div>
<div class="col-md-3">
<h2>Run & Deploy</h2>
<ul>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=517851">Run your app</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=517853">Run tools such as EF migrations and more</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=398609">Publish to Microsoft Azure Web Apps</a></li>
</ul>
</div>
</div>

View File

@ -0,0 +1,68 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - SimpleApp</title>
<environment names="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment names="Staging,Production">
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a asp-area="" asp-controller="Home" asp-action="Index" class="navbar-brand">SimpleApp</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
<li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
<li><a asp-area="" asp-controller="Home" asp-action="Contact">Contact</a></li>
</ul>
</div>
</div>
</div>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>&copy; 2016 - SimpleApp</p>
</footer>
</div>
<environment names="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>
<environment names="Staging,Production">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/bootstrap.min.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal">
</script>
<script src="~/js/site.min.js" asp-append-version="true"></script>
</environment>
@RenderSection("scripts", required: false)
@GetType().AssemblyQualifiedName
</body>
</html>

View File

@ -0,0 +1,2 @@
@using SimpleApp
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

View File

@ -0,0 +1,3 @@
@{
Layout = "_Layout";
}

View File

@ -0,0 +1,45 @@
{
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"dependencies": {
"Microsoft.AspNetCore.Mvc": "1.1.0-*",
"Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design": {
"version": "1.0.0-*",
"target": "package",
"type": "build"
},
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0-*",
"Microsoft.Extensions.Configuration.CommandLine": "1.1.0-*",
"Microsoft.Extensions.Logging.Console": "1.1.0-*"
},
"tools": {
"Microsoft.AspNetCore.Mvc.Razor.Precompilation.Tools": "1.0.0-*"
},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"version": "1.0.0",
"type": "platform"
}
}
},
"net451": {}
},
"publishOptions": {
"include": [
"wwwroot",
"appsettings.json",
"web.config"
]
},
"scripts": {
"postpublish": "dotnet razor-precompile --configuration %publish:Configuration% --framework %publish:TargetFramework% --output-path %publish:OutputPath% %publish:ProjectPath%"
}
}

3
testapps/global.json Normal file
View File

@ -0,0 +1,3 @@
{
"projects": []
}

BIN
tools/Key.snk Normal file

Binary file not shown.