Add an option to embed sources for compiled views (cshtml content) in the generated assembly
Fixes #2
This commit is contained in:
parent
b4b35138c5
commit
d046091727
|
|
@ -19,6 +19,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ApplicationWithConfigureMvc
|
|||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ClassLibraryWithPrecompiledViews", "testapps\ClassLibraryWithPrecompiledViews\ClassLibraryWithPrecompiledViews.xproj", "{4684DE8B-3FBE-421B-8798-56C3D6698B76}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PublishWIthEmbedViewSources", "testapps\PublishWIthEmbedViewSources\PublishWIthEmbedViewSources.xproj", "{E3462190-3068-40F0-9AA5-34779FE252AC}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -45,6 +47,10 @@ Global
|
|||
{4684DE8B-3FBE-421B-8798-56C3D6698B76}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4684DE8B-3FBE-421B-8798-56C3D6698B76}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4684DE8B-3FBE-421B-8798-56C3D6698B76}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E3462190-3068-40F0-9AA5-34779FE252AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E3462190-3068-40F0-9AA5-34779FE252AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E3462190-3068-40F0-9AA5-34779FE252AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E3462190-3068-40F0-9AA5-34779FE252AC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design.Internal
|
|||
{
|
||||
public static readonly string ConfigureCompilationTypeTemplate = "--configure-compilation-type";
|
||||
public static readonly string ContentRootTemplate = "--content-root";
|
||||
public static readonly string EmbedViewSourceTemplate = "--embed-view-sources";
|
||||
|
||||
public CommandArgument ProjectArgument { get; private set; }
|
||||
|
||||
|
|
@ -16,6 +17,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design.Internal
|
|||
|
||||
public CommandOption ContentRootOption { get; private set; }
|
||||
|
||||
public CommandOption EmbedViewSourcesOption { get; private set; }
|
||||
|
||||
public void Configure(CommandLineApplication app)
|
||||
{
|
||||
ProjectArgument = app.Argument(
|
||||
|
|
@ -31,6 +34,11 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design.Internal
|
|||
ContentRootTemplate,
|
||||
"The application's content root.",
|
||||
CommandOptionType.SingleValue);
|
||||
|
||||
EmbedViewSourcesOption = app.Option(
|
||||
EmbedViewSourceTemplate,
|
||||
"Embed view sources as resources in the generated assembly.",
|
||||
CommandOptionType.NoValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,9 +95,10 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design.Internal
|
|||
|
||||
var precompileAssemblyName = $"{ApplicationNameOption.Value()}{AssemblyPart.PrecompiledViewsAssemblySuffix}";
|
||||
var compilation = CompileViews(results, precompileAssemblyName);
|
||||
var resources = GetResources(results);
|
||||
|
||||
var assemblyPath = Path.Combine(OutputPathOption.Value(), precompileAssemblyName + ".dll");
|
||||
var emitResult = EmitAssembly(compilation, assemblyPath);
|
||||
var emitResult = EmitAssembly(compilation, assemblyPath, resources);
|
||||
|
||||
if (!emitResult.Success)
|
||||
{
|
||||
|
|
@ -115,7 +116,31 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design.Internal
|
|||
return 0;
|
||||
}
|
||||
|
||||
private EmitResult EmitAssembly(CSharpCompilation compilation, string assemblyPath)
|
||||
private ResourceDescription[] GetResources(ViewCompilationInfo[] results)
|
||||
{
|
||||
if (!Options.EmbedViewSourcesOption.HasValue())
|
||||
{
|
||||
return new ResourceDescription[0];
|
||||
}
|
||||
|
||||
var resources = new ResourceDescription[results.Length];
|
||||
for (var i = 0; i < results.Length; i++)
|
||||
{
|
||||
var fileInfo = results[i].RelativeFileInfo;
|
||||
|
||||
resources[i] = new ResourceDescription(
|
||||
fileInfo.RelativePath.Replace('\\', '/'),
|
||||
fileInfo.FileInfo.CreateReadStream,
|
||||
isPublic: true);
|
||||
}
|
||||
|
||||
return resources;
|
||||
}
|
||||
|
||||
private EmitResult EmitAssembly(
|
||||
CSharpCompilation compilation,
|
||||
string assemblyPath,
|
||||
ResourceDescription[] resources)
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(assemblyPath));
|
||||
|
||||
|
|
@ -127,6 +152,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Design.Internal
|
|||
emitResult = compilation.Emit(
|
||||
assemblyStream,
|
||||
pdbStream,
|
||||
manifestResources: resources,
|
||||
options: MvcServiceProvider.Compiler.EmitOptions);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Internal
|
|||
|
||||
private CommandOption BuildBasePathOption { get; set; }
|
||||
|
||||
private CommandOption DumpFilesOption { get; set; }
|
||||
|
||||
private string ProjectPath { get; set; }
|
||||
|
||||
private string Configuration { get; set; }
|
||||
|
|
@ -81,6 +83,11 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.Internal
|
|||
dispatchArgs.Add(Options.ConfigureCompilationType.Value());
|
||||
}
|
||||
|
||||
if (Options.EmbedViewSourcesOption.HasValue())
|
||||
{
|
||||
dispatchArgs.Add(CommonOptions.EmbedViewSourceTemplate);
|
||||
}
|
||||
|
||||
var compilerOptions = runtimeContext.ProjectFile.GetCompilerOptions(TargetFramework, Configuration);
|
||||
if (!string.IsNullOrEmpty(compilerOptions.KeyFile))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||
using Microsoft.DotNet.Cli.Utils;
|
||||
|
|
@ -32,6 +33,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation
|
|||
|
||||
public string TempRestoreDirectory { get; } = CreateTempRestoreDirectory();
|
||||
|
||||
public HttpClient HttpClient { get; } = new HttpClient();
|
||||
|
||||
public ILogger Logger { get; private set; }
|
||||
|
||||
public IApplicationDeployer CreateDeployment(RuntimeFlavor flavor)
|
||||
|
|
@ -66,7 +69,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation
|
|||
{
|
||||
PublishApplicationBeforeDeployment = true,
|
||||
TargetFramework = flavor == RuntimeFlavor.Clr ? "net451" : "netcoreapp1.0",
|
||||
PreservePublishedApplicationForDebugging = true,
|
||||
Configuration = "Release",
|
||||
EnvironmentVariables =
|
||||
{
|
||||
|
|
@ -93,6 +95,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation
|
|||
public virtual void Dispose()
|
||||
{
|
||||
TryDeleteDirectory(TempRestoreDirectory);
|
||||
HttpClient.Dispose();
|
||||
}
|
||||
|
||||
protected static void TryDeleteDirectory(string directory)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Precompilation.FunctionalTests
|
||||
{
|
||||
public class PublishWithEmbedViewSourcesTest
|
||||
: IClassFixture<PublishWithEmbedViewSourcesTest.PublishWithEmbedViewSourcesTestFixture>
|
||||
{
|
||||
private const string ApplicationName = "PublishWithEmbedViewSources";
|
||||
|
||||
public PublishWithEmbedViewSourcesTest(PublishWithEmbedViewSourcesTestFixture fixture)
|
||||
{
|
||||
Fixture = fixture;
|
||||
}
|
||||
|
||||
public ApplicationTestFixture Fixture { get; }
|
||||
|
||||
public static IEnumerable<object[]> SupportedFlavorsTheoryData
|
||||
{
|
||||
get
|
||||
{
|
||||
return RuntimeFlavors.SupportedFlavors.Select(f => new object[] { f });
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(SupportedFlavorsTheoryData))]
|
||||
public async Task Precompilation_CanEmbedViewSourcesAsResources(RuntimeFlavor flavor)
|
||||
{
|
||||
// Arrange
|
||||
var expectedViews = new[]
|
||||
{
|
||||
"Areas/TestArea/Views/Home/Index.cshtml",
|
||||
"Views/Home/About.cshtml",
|
||||
"Views/Home/Index.cshtml",
|
||||
};
|
||||
var expectedText = "Hello Index!";
|
||||
using (var deployer = Fixture.CreateDeployment(flavor))
|
||||
{
|
||||
var deploymentResult = deployer.Deploy();
|
||||
var assemblyPath = Path.Combine(
|
||||
deploymentResult.DeploymentParameters.PublishedApplicationRootPath,
|
||||
$"{ApplicationName}.PrecompiledViews.dll");
|
||||
|
||||
// Act - 1
|
||||
var response1 = await Fixture.HttpClient.GetStringWithRetryAsync(
|
||||
$"{deploymentResult.ApplicationBaseUri}Home/Index",
|
||||
Fixture.Logger);
|
||||
|
||||
// Assert - 1
|
||||
Assert.Equal(expectedText, response1.Trim());
|
||||
|
||||
// Act - 2
|
||||
var response2 = await Fixture.HttpClient.GetStringWithRetryAsync(
|
||||
$"{deploymentResult.ApplicationBaseUri}Home/GetPrecompiledResourceNames",
|
||||
Fixture.Logger);
|
||||
|
||||
// Assert - 2
|
||||
Assert.Equal(
|
||||
expectedViews,
|
||||
response2.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries));
|
||||
}
|
||||
}
|
||||
|
||||
public class PublishWithEmbedViewSourcesTestFixture : ApplicationTestFixture
|
||||
{
|
||||
public PublishWithEmbedViewSourcesTestFixture()
|
||||
: base(PublishWithEmbedViewSourcesTest.ApplicationName)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
Hello Index!
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace PublishWithEmbedViewSources.Controllers
|
||||
{
|
||||
public class HomeController : Controller
|
||||
{
|
||||
public IActionResult Index()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
public string GetPrecompiledResourceNames()
|
||||
{
|
||||
var precompiledAssembly = Assembly.Load(
|
||||
new AssemblyName("PublishWithEmbedViewSources.PrecompiledViews"));
|
||||
return string.Join(
|
||||
Environment.NewLine,
|
||||
precompiledAssembly.GetManifestResourceNames());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
using System.IO;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace PublishWithEmbedViewSources
|
||||
{
|
||||
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,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>e3462190-3068-40f0-9aa5-34779fe252ac</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,26 @@
|
|||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace PublishWithEmbedViewSources
|
||||
{
|
||||
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 @@
|
|||
Hello About!
|
||||
|
|
@ -0,0 +1 @@
|
|||
Hello Index!
|
||||
|
|
@ -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 --embed-view-sources --configuration %publish:Configuration% --framework %publish:TargetFramework% --output-path %publish:OutputPath% %publish:ProjectPath%"
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue