Enable component class libraries in SDK

This change contains the enabling features to use Razor Components in a
class library. Currently we require a few workarounds, see the test
project file. This is good enough to get things unblocked.

One part that was needed was to register the correct component features
in the rzc. This is a good example, of why we don't like to add new
features that get registered conditionally, it's error-prone :)

The other part that was needed was to make some of the MVC-related
features for assembly attributes conditional on the TFM. We need to be
able to use the 3.0 (all inclusive) SDK, but without the MVC-related
features. This isn't the right heuristic, but it gets us unblocked.
\n\nCommit migrated from 8dbf02076b
This commit is contained in:
Ryan Nowak 2018-12-27 22:15:23 -08:00
parent 0c1c05efc6
commit 14a8159919
10 changed files with 108 additions and 7 deletions

View File

@ -142,6 +142,11 @@ namespace Microsoft.AspNetCore.Razor.Tools
b.Features.Add(new CompilationTagHelperFeature());
b.Features.Add(new DefaultTagHelperDescriptorProvider());
b.Features.Add(new ComponentTagHelperDescriptorProvider());
b.Features.Add(new BindTagHelperDescriptorProvider());
b.Features.Add(new EventHandlerTagHelperDescriptorProvider());
b.Features.Add(new RefTagHelperDescriptorProvider());
b.Features.Add(new DefaultTypeNameFeature());
});
var feature = engine.Engine.Features.OfType<ITagHelperFeature>().Single();

View File

@ -7,6 +7,7 @@ using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis.Razor;
using Microsoft.Extensions.CommandLineUtils;
using Microsoft.VisualStudio.LanguageServices.Razor.Serialization;
using Newtonsoft.Json;
@ -169,6 +170,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
var engine = RazorProjectEngine.Create(configuration, compositeFileSystem, b =>
{
b.Features.Add(new StaticTagHelperFeature() { TagHelpers = tagHelpers, });
b.Features.Add(new DefaultTypeNameFeature());
if (GenerateDeclaration.HasValue())
{

View File

@ -10,6 +10,11 @@ Copyright (c) .NET Foundation. All rights reserved.
***********************************************************************************************
-->
<Project ToolsVersion="14.0">
<PropertyGroup>
<_TargetingNETCoreApp30OrLater Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(_TargetFrameworkVersionWithoutV)' &gt; '2.9'">true</_TargetingNETCoreApp30OrLater>
</PropertyGroup>
<!--
Initialize properties and items inferred using the project version. This file is not imported in projects referencing
MVC \ Razor 2.2 or earlier since values specified here are provided via targets and props imported from NuGet packages
@ -17,18 +22,21 @@ Copyright (c) .NET Foundation. All rights reserved.
The properties and items here are designed to be read by CPS so they should be just simple evaluation-time values
and should not require targets to initialize.
Also, these values are based on whether the library is targeting netcoreapp3.0 for now. A better heuristic
would be to detect whether the ASP.NET Core shared framework is referenced.
-->
<PropertyGroup>
<!--
MVC uses a ProvideApplicationPartFactoryAttribute on the generated assembly to load compiled views from assembly. Set this to false, to prevent generating this attribute.
-->
<GenerateProvideApplicationPartFactoryAttribute Condition="'$(GenerateProvideApplicationPartFactoryAttribute)'==''">true</GenerateProvideApplicationPartFactoryAttribute>
<GenerateProvideApplicationPartFactoryAttribute Condition="'$(GenerateProvideApplicationPartFactoryAttribute)'==''">$(_TargetingNETCoreApp30OrLater)</GenerateProvideApplicationPartFactoryAttribute>
<!--
Determines if the Sdk is allowed to add additional attributes to the project assembly.
For instance, MVC will generally want to add attributes to support view discovery and runtime compilation.
-->
<GenerateRazorAssemblyInfo Condition="'$(GenerateRazorAssemblyInfo)'==''">true</GenerateRazorAssemblyInfo>
<GenerateRazorAssemblyInfo Condition="'$(GenerateRazorAssemblyInfo)'==''">$(_TargetingNETCoreApp30OrLater)</GenerateRazorAssemblyInfo>
<!--
MVC will generally want to add support for runtime compilation, but only for applications.
@ -44,10 +52,6 @@ Copyright (c) .NET Foundation. All rights reserved.
<IsRazorCompilerReferenced Condition="'$(IsRazorCompilerReferenced)'==''">true</IsRazorCompilerReferenced>
</PropertyGroup>
<PropertyGroup>
<_TargetingNETCoreApp30OrLater Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(_TargetFrameworkVersionWithoutV)' &gt; '2.9'">true</_TargetingNETCoreApp30OrLater>
</PropertyGroup>
<PropertyGroup Condition="'$(RazorLangVersion)'==''">
<RazorLangVersion Condition="'$(_TargetingNETCoreApp30OrLater)' == 'true'">3.0</RazorLangVersion>

View File

@ -89,7 +89,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
// Assert - 2
Assert.BuildPassed(result);
Assert.FileContentEquals(result, tagHelperOutputCache, "[]");
Assert.FileDoesNotContain(result, tagHelperOutputCache, @"""Name"":""SimpleMvc.SimpleTagHelper""");
var newThumbPrint = GetThumbPrint(generatedFile);
Assert.NotEqual(fileThumbPrint, newThumbPrint);
}

View File

@ -672,6 +672,22 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
Assert.FileDoesNotExist(result, IntermediateOutputPath, "SimpleMvc.Views.dll");
}
[Fact]
[InitializeTestProject("ComponentLibrary")]
public async Task Building_NetstandardComponentLibrary()
{
TargetFramework = "netstandard2.0";
// Build
var result = await DotnetMSBuild("Build");
Assert.BuildPassed(result);
Assert.FileExists(result, OutputPath, "ComponentLibrary.dll");
Assert.FileExists(result, OutputPath, "ComponentLibrary.pdb");
Assert.FileDoesNotExist(result, OutputPath, "ComponentLibrary.Views.dll");
Assert.FileDoesNotExist(result, OutputPath, "ComponentLibrary.Views.pdb");
}
private static DependencyContext ReadDependencyContext(string depsFilePath)
{
var reader = new DependencyContextJsonReader();

View File

@ -15,6 +15,8 @@
<_EnableAllInclusiveRazorSdk>true</_EnableAllInclusiveRazorSdk>
<RazorLangVersion>3.0</RazorLangVersion>
<RazorDefaultConfiguration>MVC-3.0</RazorDefaultConfiguration>
<GenerateRazorAssemblyInfo>true</GenerateRazorAssemblyInfo>
<GenerateProvideApplicationPartFactoryAttribute>true</GenerateProvideApplicationPartFactoryAttribute>
</PropertyGroup>
<PropertyGroup Condition="'$(RunningAsTest)' == ''">

View File

@ -0,0 +1,12 @@
using System;
namespace ComponentLibrary
{
public class Class1
{
public void Method()
{
Console.WriteLine(typeof(Class1));
}
}
}

View File

@ -0,0 +1,51 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<RazorSdkDirectoryRoot>$(RazorSdkArtifactsDirectory)$(Configuration)\sdk-output\</RazorSdkDirectoryRoot>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<_EnableAllInclusiveRazorSdk>true</_EnableAllInclusiveRazorSdk>
<RazorLangVersion>3.0</RazorLangVersion>
<RazorDefaultConfiguration>MVC-3.0</RazorDefaultConfiguration>
</PropertyGroup>
<PropertyGroup Condition="'$(RunningAsTest)' == ''">
<!-- We don't want to run build server when not running as tests. -->
<UseRazorBuildServer>false</UseRazorBuildServer>
</PropertyGroup>
<!-- DO NOT add addition references here. This is meant to simulate a non-MVC library -->
<ItemGroup Condition="'$(BinariesRoot)'==''">
<!-- In test scenarios $(BinariesRoot) is defined in a generated Directory.Build.props file -->
<ProjectReference Include="..\..\Microsoft.AspNetCore.Razor.Test.ComponentShim\Microsoft.AspNetCore.Razor.Test.ComponentShim.csproj"/>
</ItemGroup>
<ItemGroup Condition="'$(BinariesRoot)'!=''">
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.Test.ComponentShim.dll"/>
</ItemGroup>
<!--
BEGIN COMPONENT .cshtml WORKAROUND
This is the current workaround used by the components codebase to treat .cshtml files as components
so that we can have tooling support. Testing it here so it won't break.
-->
<ItemGroup>
<RazorComponent Include="@(Content->WithMetadataValue('Extension', '.cshtml'))" />
</ItemGroup>
<Target Name="_RemoveFilesFromRazorGenerate" AfterTargets="ResolveRazorGenerateInputs">
<ItemGroup>
<RazorGenerate Remove="@(RazorGenerate)" />
</ItemGroup>
</Target>
<!--
END COMPONENT .cshtml WORKAROUND
-->
<!-- Test Placeholder -->
</Project>

View File

@ -0,0 +1,8 @@
@typeparam TItem
<h1>@Title - @Item</h1>
@functions {
[Parameter] TItem Item { get; set; }
[Parameter] string Title { get; set; }
}

View File

@ -0,0 +1 @@
<GenericComponent Item="17" Title="nameof(Class1)" />