Adding Razor Precompilation
This commit is contained in:
parent
6f5722366d
commit
dbe93ac6b1
|
|
@ -35,4 +35,5 @@ nuget.exe
|
|||
*.sln.ide
|
||||
node_modules
|
||||
*launchSettings.json
|
||||
*.orig
|
||||
*.orig
|
||||
BuildInfo.generated.cs
|
||||
|
|
@ -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
|
||||
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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"
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"projects": ["src", "test/WebSites", "samples"]
|
||||
"projects": ["src", "samples"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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")]
|
||||
|
|
@ -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": {}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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")]
|
||||
|
|
@ -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": {}
|
||||
}
|
||||
}
|
||||
|
|
@ -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")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
using Xunit;
|
||||
|
||||
[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)]
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
AspNetCore.Views_Home_Index_cshtml, ApplicationWithConfigureMvc.PrecompiledViews, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
|
||||
<br />Hello world!
|
||||
|
|
@ -0,0 +1 @@
|
|||
Hello from Test123
|
||||
|
|
@ -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>© 2016 - ApplicationWithTagHelpers</p>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
AspNetCore.Views_Shared__Layout_cshtml, ApplicationWithTagHelpers.PrecompiledViews, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -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>© 2016 - ApplicationWithTagHelpers</p>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
AspNetCore.Views_Shared__Layout_cshtml, ApplicationWithTagHelpers.PrecompiledViews, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -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>© 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>
|
||||
|
|
@ -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")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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"
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace ApplicationWithConfigureStartup.Controllers
|
||||
{
|
||||
public class HomeController : Controller
|
||||
{
|
||||
public IActionResult Index() => View();
|
||||
|
||||
public IActionResult ViewWithPreprocessor() => View();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
@GetType().AssemblyQualifiedName
|
||||
Hello world!
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
@{
|
||||
var message = "Hello world message";
|
||||
#if TEST123
|
||||
message = "Hello from Test123";
|
||||
#endif
|
||||
}
|
||||
@message
|
||||
|
|
@ -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%"
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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?}");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
@addTagHelper *, ClassLibraryTagHelper
|
||||
|
||||
@GetType().AssemblyQualifiedName
|
||||
<div bold="bold">To boldy tag that no one has ever tagged before...</div>
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
@addTagHelper *, ApplicationWithTagHelpers
|
||||
|
||||
@GetType().AssemblyQualifiedName
|
||||
<test controller="Home" action="About"></test>
|
||||
|
||||
|
||||
|
||||
|
|
@ -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>
|
||||
|
||||
|
||||
|
|
@ -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>© 2016 - ApplicationWithTagHelpers</p>
|
||||
</footer>
|
||||
</div>
|
||||
@RenderSection("scripts", required: false)
|
||||
@GetType().AssemblyQualifiedName
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
@using ApplicationWithTagHelpers
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
@{
|
||||
Layout = "_Layout";
|
||||
}
|
||||
|
|
@ -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%"
|
||||
}
|
||||
}
|
||||
|
|
@ -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>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Razor.Runtime": "1.1.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"netstandard1.6": {},
|
||||
"net451": {}
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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?}");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
@{
|
||||
ViewData["Title"] = "About";
|
||||
}
|
||||
<h2>@ViewData["Title"].</h2>
|
||||
<h3>@ViewData["Message"]</h3>
|
||||
|
||||
<p>Use this area to provide additional information.</p>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>© 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>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
@using SimpleApp
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
@{
|
||||
Layout = "_Layout";
|
||||
}
|
||||
|
|
@ -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%"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"projects": []
|
||||
}
|
||||
Binary file not shown.
Loading…
Reference in New Issue