From d968fdd31fb869414a416c0dfd4902a359b4f84a Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Sat, 20 Jan 2018 12:34:38 -0800 Subject: [PATCH] [Fixes #1580, #1581] Update Identity UI to use Razor precompilation * Switch from using the embedded file provider for the precompiled views for actual razor precompilation. * Add MSBuild props and targets file to include additional assembly attributes on the generated precompiled views. --- NuGetPackageVerifier.json | 5 +- build/dependencies.props | 103 +++++++++--------- korebuild-lock.txt | 4 +- .../Areas/Identity/Pages/_ViewStart.cshtml | 3 + .../Views/Shared/_Layout.cshtml | 2 +- src/UI/IdentityBuilderUIExtensions.cs | 68 ++++++++++++ src/UI/IdentityDefaultUIConfigureOptions.cs | 10 -- .../Microsoft.AspNetCore.Identity.UI.csproj | 30 +++-- src/UI/Microsoft.AspNetCore.Identity.UI.props | 24 ++++ .../Microsoft.AspNetCore.Identity.UI.targets | 91 ++++++++++++++++ 10 files changed, 267 insertions(+), 73 deletions(-) create mode 100644 samples/IdentitySample.DefaultUI/Areas/Identity/Pages/_ViewStart.cshtml create mode 100644 src/UI/Microsoft.AspNetCore.Identity.UI.props create mode 100644 src/UI/Microsoft.AspNetCore.Identity.UI.targets diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index c0c51483cb..e128da1478 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -7,8 +7,9 @@ "Microsoft.AspNetCore.Identity.UI": { "Exclusions": { "DOC_MISSING": { - "lib/netstandard2.0/Microsoft.AspNetCore.Identity.UI.dll": "This is a library with packages UI" - } + "lib/netstandard2.0/Microsoft.AspNetCore.Identity.UI.dll": "This is a library with packaged UI", + "lib/netstandard2.0/Microsoft.AspNetCore.Identity.UI.PrecompiledViews.dll": "This assembly is generated and contains precompiled razor pages" + } } } } diff --git a/build/dependencies.props b/build/dependencies.props index 4b6a766d64..bcb468427b 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,65 +3,66 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15651 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 + 2.1.0-preview1-15678 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 2.2.1 2.3.2 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 - 2.1.0-preview1-28061 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 + 2.1.0-preview1-28135 3.14.2 5.2.0-preview2-41113220915 2.0.0 - 2.1.0-preview1-26016-05 + 2.1.0-preview1-26115-03 15.3.0 3.0.1 - 2.1.0-preview1-28061 + 2.1.0-preview1-28135 4.7.49 - 4.5.0-preview1-26016-05 + 4.5.0-preview1-26112-01 0.8.0 2.3.1 2.3.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 2146d006d7..84f798d53f 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15661 -commithash:c9349d4c8a495d3085d9b879214d80f2f45e2193 +version:2.1.0-preview1-15678 +commithash:5347461137cb45a77ddcc0b55b2478092de43338 diff --git a/samples/IdentitySample.DefaultUI/Areas/Identity/Pages/_ViewStart.cshtml b/samples/IdentitySample.DefaultUI/Areas/Identity/Pages/_ViewStart.cshtml new file mode 100644 index 0000000000..c4284f6c20 --- /dev/null +++ b/samples/IdentitySample.DefaultUI/Areas/Identity/Pages/_ViewStart.cshtml @@ -0,0 +1,3 @@ +@{ + Layout = "/Views/Shared/_Layout.cshtml"; +} diff --git a/samples/IdentitySample.DefaultUI/Views/Shared/_Layout.cshtml b/samples/IdentitySample.DefaultUI/Views/Shared/_Layout.cshtml index 15c0be6c6a..d0d0d86988 100644 --- a/samples/IdentitySample.DefaultUI/Views/Shared/_Layout.cshtml +++ b/samples/IdentitySample.DefaultUI/Views/Shared/_Layout.cshtml @@ -31,7 +31,7 @@ @RenderBody()
-

© 2016 - IdentitySample

+

© 2018 - IdentitySample.DefaultUI

diff --git a/src/UI/IdentityBuilderUIExtensions.cs b/src/UI/IdentityBuilderUIExtensions.cs index 0df03f0d24..060fc277ec 100644 --- a/src/UI/IdentityBuilderUIExtensions.cs +++ b/src/UI/IdentityBuilderUIExtensions.cs @@ -1,8 +1,13 @@ // 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 System.Linq; +using System.Reflection; using Microsoft.AspNetCore.Identity.UI; using Microsoft.AspNetCore.Identity.UI.Services; +using Microsoft.AspNetCore.Mvc.ApplicationParts; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -26,10 +31,73 @@ namespace Microsoft.AspNetCore.Identity /// The . public static IdentityBuilder AddDefaultUI(this IdentityBuilder builder) { + AddAdditionalApplicationParts(builder); + builder.Services.ConfigureOptions(); builder.Services.TryAddTransient(); return builder; } + + private static void AddAdditionalApplicationParts(IdentityBuilder builder) + { + // For preview1, we don't have a good mechanism to plug in additional parts. + // We need to provide API surface to allow libraries to plug in existing parts + // that were optionally added. + // Challenges here are: + // * Discovery of the parts. + // * Ordering of the parts. + // * Loading of the assembly in memory. + var thisAssembly = typeof(IdentityBuilderUIExtensions).Assembly; + var additionalReferences = thisAssembly + .GetCustomAttributes() + .Where(am => string.Equals(am.Key, "Microsoft.AspNetCore.Mvc.AdditionalReference")) + .Select(am => am.Value.Split(',')[0]) + .ToArray(); + + var mvcBuilder = builder.Services + .AddMvc() + .ConfigureApplicationPartManager(apm => + { + foreach (var reference in additionalReferences) + { + var fileName = Path.GetFileName(reference); + var filePath = Path.Combine(Path.GetDirectoryName(thisAssembly.Location), fileName); + var additionalAssembly = LoadAssembly(filePath); + // This needs to change to additional assembly part. + var additionalPart = new AssemblyPart(additionalAssembly); + if (!apm.ApplicationParts.Any(ap => HasSameName(ap.Name, additionalPart.Name))) + { + apm.ApplicationParts.Add(additionalPart); + } + } + }); + + bool HasSameName(string left, string right) => string.Equals(left, right, StringComparison.Ordinal); + } + + private static Assembly LoadAssembly(string filePath) + { + Assembly viewsAssembly = null; + if (File.Exists(filePath)) + { + try + { + viewsAssembly = Assembly.LoadFile(filePath); + } + catch (FileLoadException) + { + throw new InvalidOperationException("Unable to load the precompiled views assembly in " + + $"'{filePath}'."); + } + } + else + { + throw new InvalidOperationException("Could not find the precompiled views assembly for 'Microsoft.AspNetCore.Identity.UI' at " + + $"'{filePath}'."); + } + + return viewsAssembly; + } } } \ No newline at end of file diff --git a/src/UI/IdentityDefaultUIConfigureOptions.cs b/src/UI/IdentityDefaultUIConfigureOptions.cs index d80ecc77b7..ce475a1916 100644 --- a/src/UI/IdentityDefaultUIConfigureOptions.cs +++ b/src/UI/IdentityDefaultUIConfigureOptions.cs @@ -5,7 +5,6 @@ using System; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.FileProviders; @@ -15,7 +14,6 @@ namespace Microsoft.AspNetCore.Identity.UI { internal class IdentityDefaultUIConfigureOptions : IPostConfigureOptions, - IPostConfigureOptions, IPostConfigureOptions, IPostConfigureOptions { @@ -34,14 +32,6 @@ namespace Microsoft.AspNetCore.Identity.UI options.AllowAreas = true; } - public void PostConfigure(string name, RazorViewEngineOptions options) - { - name = name ?? throw new ArgumentNullException(nameof(name)); - options = options ?? throw new ArgumentNullException(nameof(options)); - - options.FileProviders.Add(new ManifestEmbeddedFileProvider(GetType().Assembly)); - } - public void PostConfigure(string name, StaticFileOptions options) { name = name ?? throw new ArgumentNullException(nameof(name)); diff --git a/src/UI/Microsoft.AspNetCore.Identity.UI.csproj b/src/UI/Microsoft.AspNetCore.Identity.UI.csproj index d8fec1a076..7d43aa814b 100644 --- a/src/UI/Microsoft.AspNetCore.Identity.UI.csproj +++ b/src/UI/Microsoft.AspNetCore.Identity.UI.csproj @@ -2,31 +2,47 @@ ASP.NET Core Identity UI is the default Razor Pages built-in UI for the ASP.NET Core Identity framework. + Precompiled views assembly for the ASP.NET Core Identity UI package. netstandard2.0 false aspnetcore;identity;membership;razorpages false true + true + RazorSdk + $(RazorTargetName).dll - - - - - - - + + + + + + + + + + + + + + <_parameter1>Microsoft.AspNetCore.Mvc.AdditionalReference + <_parameter2>$(RazorTargetName).dll,false + + + + diff --git a/src/UI/Microsoft.AspNetCore.Identity.UI.props b/src/UI/Microsoft.AspNetCore.Identity.UI.props new file mode 100644 index 0000000000..cef7fa2ea5 --- /dev/null +++ b/src/UI/Microsoft.AspNetCore.Identity.UI.props @@ -0,0 +1,24 @@ + + + true + + + + true + true + true + true + true + true + true + true + true + true + + + + + + + + \ No newline at end of file diff --git a/src/UI/Microsoft.AspNetCore.Identity.UI.targets b/src/UI/Microsoft.AspNetCore.Identity.UI.targets new file mode 100644 index 0000000000..acd6c777d4 --- /dev/null +++ b/src/UI/Microsoft.AspNetCore.Identity.UI.targets @@ -0,0 +1,91 @@ + + + + + + + + <_Parameter1>$(Company) + + + <_Parameter1>$(Configuration) + + + <_Parameter1>$(Copyright) + + + <_Parameter1>$(PrecompiledDescription) + + + <_Parameter1>$(FileVersion) + + + <_Parameter1>$(InformationalVersion) + + + <_Parameter1>$(Product) + + + <_Parameter1>$(PrecompiledAssemblyTitle) + + + <_Parameter1>$(AssemblyVersion) + + + <_Parameter1>$(NeutralLanguage) + + + <_Parameter1>BuildNumber + <_Parameter2>$(BuildNumber) + + + + + + + + $(IntermediateOutputPath)$(MSBuildProjectName).PrecompiledViews.AssemblyInfo$(DefaultLanguageSourceExtension) + $(IntermediateOutputPath)$(MSBuildProjectName).PrecompiledViews.AssemblyInfoInputs.cache + + + + + + + + + + + + + + + + + $(IntermediateOutputPath)$(MSBuildProjectName).PrecompiledViews.AssemblyInfo$(DefaultLanguageSourceExtension) + + + + + + + + + + + + + + + + \ No newline at end of file