Do build time discovery of MVC ApplicationParts (dotnet/aspnetcore-tooling#598)
* Do build time discovery of MVC ApplicationParts
\n\nCommit migrated from e79d5600f7
This commit is contained in:
parent
96475e488d
commit
b5a7daba2b
|
|
@ -0,0 +1,14 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.Tasks
|
||||||
|
{
|
||||||
|
public class AssemblyItem
|
||||||
|
{
|
||||||
|
public string Path { get; set; }
|
||||||
|
|
||||||
|
public bool IsSystemReference { get; set; }
|
||||||
|
|
||||||
|
public string AssemblyName { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>Razor is a markup syntax for adding server-side logic to web pages. This package contains MSBuild support for Razor.</Description>
|
<Description>Razor is a markup syntax for adding server-side logic to web pages. This package contains MSBuild support for Razor.</Description>
|
||||||
<TargetFrameworks>netcoreapp3.0;netstandard2.0;net46</TargetFrameworks>
|
<TargetFrameworks>netcoreapp3.0;net46</TargetFrameworks>
|
||||||
|
|
||||||
<TargetName>Microsoft.NET.Sdk.Razor.Tasks</TargetName>
|
<TargetName>Microsoft.NET.Sdk.Razor.Tasks</TargetName>
|
||||||
<NuspecFile>$(MSBuildProjectName).nuspec</NuspecFile>
|
<NuspecFile>$(MSBuildProjectName).nuspec</NuspecFile>
|
||||||
|
|
@ -17,8 +17,9 @@
|
||||||
<PackageReference Include="Microsoft.Build.Framework" Version="$(MicrosoftBuildFrameworkPackageVersion)" />
|
<PackageReference Include="Microsoft.Build.Framework" Version="$(MicrosoftBuildFrameworkPackageVersion)" />
|
||||||
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="$(MicrosoftBuildUtilitiesCorePackageVersion)" />
|
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="$(MicrosoftBuildUtilitiesCorePackageVersion)" />
|
||||||
<PackageReference Include="Microsoft.Extensions.CommandLineUtils.Sources" Version="$(MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion)" />
|
<PackageReference Include="Microsoft.Extensions.CommandLineUtils.Sources" Version="$(MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion)" />
|
||||||
|
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataPackageVersion)" Condition="'$(TargetFramework)'=='net46'" />
|
||||||
|
|
||||||
<ProjectReference Include="..\Microsoft.AspNetCore.Mvc.Razor.Extensions\Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj" ReferenceOutputAssembly="false" Condition="'$(TargetFramework)'=='netstandard2.0'" />
|
<ProjectReference Include="..\Microsoft.AspNetCore.Mvc.Razor.Extensions\Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj" ReferenceOutputAssembly="false" Condition="'$(TargetFramework)'=='netcoreapp3.0'" />
|
||||||
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Tools\Microsoft.AspNetCore.Razor.Tools.csproj" ReferenceOutputAssembly="false" Condition="'$(TargetFramework)'=='netcoreapp3.0'" />
|
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Tools\Microsoft.AspNetCore.Razor.Tools.csproj" ReferenceOutputAssembly="false" Condition="'$(TargetFramework)'=='netcoreapp3.0'" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
@ -54,7 +55,10 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectOutput Include="$(ArtifactsBinDir)Microsoft.NET.Sdk.Razor\$(Configuration)\net46*\Microsoft.NET.Sdk.Razor.Tasks.*" />
|
<ProjectOutput Include="$(ArtifactsBinDir)Microsoft.NET.Sdk.Razor\$(Configuration)\net46*\Microsoft.NET.Sdk.Razor.Tasks.*" />
|
||||||
<ProjectOutput Include="$(ArtifactsBinDir)Microsoft.NET.Sdk.Razor\$(Configuration)\netstandard2.0*\Microsoft.NET.Sdk.Razor.Tasks.*" />
|
<ProjectOutput Include="$(ArtifactsBinDir)Microsoft.NET.Sdk.Razor\$(Configuration)\netcoreapp3.0*\Microsoft.NET.Sdk.Razor.Tasks.*" />
|
||||||
|
|
||||||
|
<ProjectOutput Include="$(ArtifactsBinDir)Microsoft.NET.Sdk.Razor\$(Configuration)\net46*\System.Collections.Immutable.dll" />
|
||||||
|
<ProjectOutput Include="$(ArtifactsBinDir)Microsoft.NET.Sdk.Razor\$(Configuration)\net46*\System.Reflection.Metadata.dll" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Copy SourceFiles="@(ProjectOutput)" DestinationFiles="$(SdkOutputPath)tasks\%(RecursiveDir)%(FileName)%(Extension)" SkipUnchangedFiles="true">
|
<Copy SourceFiles="@(ProjectOutput)" DestinationFiles="$(SdkOutputPath)tasks\%(RecursiveDir)%(FileName)%(Extension)" SkipUnchangedFiles="true">
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,169 @@
|
||||||
|
// 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.Reflection.Metadata;
|
||||||
|
using System.Reflection.PortableExecutable;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.Tasks
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Resolves assemblies that reference one of the specified "targetAssemblies" either directly or transitively.
|
||||||
|
/// </summary>
|
||||||
|
public class ReferenceResolver
|
||||||
|
{
|
||||||
|
private readonly HashSet<string> _mvcAssemblies;
|
||||||
|
private readonly Dictionary<string, ClassifiedAssemblyItem> _lookup = new Dictionary<string, ClassifiedAssemblyItem>(StringComparer.Ordinal);
|
||||||
|
|
||||||
|
public ReferenceResolver(IReadOnlyList<string> targetAssemblies, IReadOnlyList<AssemblyItem> assemblyItems)
|
||||||
|
{
|
||||||
|
_mvcAssemblies = new HashSet<string>(targetAssemblies, StringComparer.Ordinal);
|
||||||
|
|
||||||
|
foreach (var item in assemblyItems)
|
||||||
|
{
|
||||||
|
var classifiedItem = new ClassifiedAssemblyItem(item);
|
||||||
|
_lookup[item.AssemblyName] = classifiedItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IReadOnlyList<string> ResolveAssemblies()
|
||||||
|
{
|
||||||
|
var applicationParts = new List<string>();
|
||||||
|
foreach (var item in _lookup)
|
||||||
|
{
|
||||||
|
var classification = Resolve(item.Value);
|
||||||
|
if (classification == DependencyClassification.ReferencesMvc)
|
||||||
|
{
|
||||||
|
applicationParts.Add(item.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's not interesting for us to know if a dependency has a classification of MvcReference.
|
||||||
|
// All applications targeting the Microsoft.AspNetCore.App will have have a reference to Mvc.
|
||||||
|
}
|
||||||
|
|
||||||
|
return applicationParts;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DependencyClassification Resolve(ClassifiedAssemblyItem classifiedItem)
|
||||||
|
{
|
||||||
|
if (classifiedItem.DependencyClassification != DependencyClassification.Unknown)
|
||||||
|
{
|
||||||
|
return classifiedItem.DependencyClassification;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classifiedItem.AssemblyItem == null)
|
||||||
|
{
|
||||||
|
// We encountered a dependency that isn't part of this assembly's dependency set. We'll see if it happens to be an MVC assembly.
|
||||||
|
// This might be useful in scenarios where the app does not have a framework reference at the entry point,
|
||||||
|
// but the transitive dependency does.
|
||||||
|
classifiedItem.DependencyClassification = _mvcAssemblies.Contains(classifiedItem.Name) ?
|
||||||
|
DependencyClassification.MvcReference :
|
||||||
|
DependencyClassification.DoesNotReferenceMvc;
|
||||||
|
|
||||||
|
return classifiedItem.DependencyClassification;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classifiedItem.AssemblyItem.IsSystemReference)
|
||||||
|
{
|
||||||
|
// We do not allow transitive references to MVC via a framework reference to count.
|
||||||
|
// e.g. depending on Microsoft.AspNetCore.SomeThingNewThatDependsOnMvc would not result in an assembly being treated as
|
||||||
|
// referencing MVC.
|
||||||
|
classifiedItem.DependencyClassification = _mvcAssemblies.Contains(classifiedItem.Name) ?
|
||||||
|
DependencyClassification.MvcReference :
|
||||||
|
DependencyClassification.DoesNotReferenceMvc;
|
||||||
|
|
||||||
|
return classifiedItem.DependencyClassification;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_mvcAssemblies.Contains(classifiedItem.Name))
|
||||||
|
{
|
||||||
|
classifiedItem.DependencyClassification = DependencyClassification.MvcReference;
|
||||||
|
return classifiedItem.DependencyClassification;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dependencyClassification = DependencyClassification.DoesNotReferenceMvc;
|
||||||
|
foreach (var assemblyItem in GetReferences(classifiedItem.AssemblyItem.Path))
|
||||||
|
{
|
||||||
|
var classification = Resolve(assemblyItem);
|
||||||
|
if (classification == DependencyClassification.MvcReference || classification == DependencyClassification.ReferencesMvc)
|
||||||
|
{
|
||||||
|
dependencyClassification = DependencyClassification.ReferencesMvc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
classifiedItem.DependencyClassification = dependencyClassification;
|
||||||
|
return dependencyClassification;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual IReadOnlyList<ClassifiedAssemblyItem> GetReferences(string file)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var peReader = new PEReader(File.OpenRead(file));
|
||||||
|
if (!peReader.HasMetadata)
|
||||||
|
{
|
||||||
|
return Array.Empty<ClassifiedAssemblyItem>(); // not a managed assembly
|
||||||
|
}
|
||||||
|
|
||||||
|
var metadataReader = peReader.GetMetadataReader();
|
||||||
|
|
||||||
|
var assemblyItems = new List<ClassifiedAssemblyItem>();
|
||||||
|
foreach (var handle in metadataReader.AssemblyReferences)
|
||||||
|
{
|
||||||
|
var reference = metadataReader.GetAssemblyReference(handle);
|
||||||
|
var referenceName = metadataReader.GetString(reference.Name);
|
||||||
|
|
||||||
|
if (_lookup.TryGetValue(referenceName, out var classifiedItem))
|
||||||
|
{
|
||||||
|
assemblyItems.Add(classifiedItem);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// A dependency references an item that isn't referenced by this project.
|
||||||
|
// We'll construct an item for so that we can calculate the classification based on it's name.
|
||||||
|
assemblyItems.Add(new ClassifiedAssemblyItem(referenceName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return assemblyItems;
|
||||||
|
}
|
||||||
|
catch (BadImageFormatException)
|
||||||
|
{
|
||||||
|
// not a PE file, or invalid metadata
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.Empty<ClassifiedAssemblyItem>(); // not a managed assembly
|
||||||
|
}
|
||||||
|
|
||||||
|
protected enum DependencyClassification
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
DoesNotReferenceMvc,
|
||||||
|
ReferencesMvc,
|
||||||
|
MvcReference,
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class ClassifiedAssemblyItem
|
||||||
|
{
|
||||||
|
public ClassifiedAssemblyItem(AssemblyItem classifiedItem)
|
||||||
|
: this(classifiedItem.AssemblyName)
|
||||||
|
{
|
||||||
|
AssemblyItem = classifiedItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassifiedAssemblyItem(string name)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; }
|
||||||
|
|
||||||
|
public AssemblyItem AssemblyItem { get; }
|
||||||
|
|
||||||
|
public DependencyClassification DependencyClassification { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
// 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.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using Microsoft.Build.Framework;
|
||||||
|
using Microsoft.Build.Utilities;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.Tasks
|
||||||
|
{
|
||||||
|
public class FindAssembliesWithReferencesTo : Task
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public ITaskItem[] TargetAssemblyNames { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public ITaskItem[] Assemblies { get; set; }
|
||||||
|
|
||||||
|
[Output]
|
||||||
|
public string[] ResolvedAssemblies { get; set; }
|
||||||
|
|
||||||
|
public override bool Execute()
|
||||||
|
{
|
||||||
|
var referenceItems = new List<AssemblyItem>();
|
||||||
|
foreach (var item in Assemblies)
|
||||||
|
{
|
||||||
|
const string FusionNameKey = "FusionName";
|
||||||
|
var fusionName = item.GetMetadata(FusionNameKey);
|
||||||
|
if (string.IsNullOrEmpty(fusionName))
|
||||||
|
{
|
||||||
|
Log.LogError($"Missing required metadata '{FusionNameKey}' for '{item.ItemSpec}.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var assemblyName = new AssemblyName(fusionName).Name;
|
||||||
|
referenceItems.Add(new AssemblyItem
|
||||||
|
{
|
||||||
|
AssemblyName = assemblyName,
|
||||||
|
IsSystemReference = item.GetMetadata("IsSystemReference") == "true",
|
||||||
|
Path = item.ItemSpec,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var targetAssemblyNames = TargetAssemblyNames.Select(s => s.ItemSpec).ToList();
|
||||||
|
|
||||||
|
var provider = new ReferenceResolver(targetAssemblyNames, referenceItems);
|
||||||
|
var assemblyNames = provider.ResolveAssemblies();
|
||||||
|
|
||||||
|
ResolvedAssemblies = assemblyNames.ToArray();
|
||||||
|
|
||||||
|
return !Log.HasLoggedErrors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,90 @@
|
||||||
|
<!--
|
||||||
|
***********************************************************************************************
|
||||||
|
Microsoft.NET.Sdk.Razor.ApplicationPartsDiscovery
|
||||||
|
|
||||||
|
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
|
||||||
|
created a backup copy. Incorrect changes to this file will make it
|
||||||
|
impossible to load or build your projects from the command-line or the IDE.
|
||||||
|
|
||||||
|
Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
***********************************************************************************************
|
||||||
|
-->
|
||||||
|
|
||||||
|
<Project ToolsVersion="14.0">
|
||||||
|
<UsingTask
|
||||||
|
TaskName="Microsoft.AspNetCore.Razor.Tasks.FindAssembliesWithReferencesTo"
|
||||||
|
AssemblyFile="$(RazorSdkBuildTasksAssembly)"
|
||||||
|
Condition="'$(RazorSdkBuildTasksAssembly)' != ''" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<GenerateMvcApplicationPartsAttribute Condition="'$(GenerateMvcApplicationPartsAssemblyAttributes)' == '' AND '$(OutputType)' == 'Exe'">true</GenerateMvcApplicationPartsAttribute>
|
||||||
|
|
||||||
|
<CoreCompileDependsOn Condition="'$(GenerateMvcApplicationPartsAttribute)' == 'true' AND '$(DesignTimeBuild)' != 'true'">
|
||||||
|
_DiscoverMvcApplicationParts;
|
||||||
|
$(CoreCompileDependsOn);
|
||||||
|
</CoreCompileDependsOn>
|
||||||
|
|
||||||
|
<_MvcApplicationPartAttributeGeneratedFile>$(IntermediateOutputPath)$(TargetName).MvcApplicationPartsAssemblyInfo$(DefaultLanguageSourceExtension)</_MvcApplicationPartAttributeGeneratedFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Target
|
||||||
|
Name="_DiscoverMvcApplicationParts"
|
||||||
|
Inputs="$(ProjectAssetsFile);$(MSBuildAllProjects)"
|
||||||
|
Outputs="$(_MvcApplicationPartAttributeGeneratedFile)"
|
||||||
|
DependsOnTargets="ResolveAssemblyReferences">
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<_MvcAssemblyName Include="Microsoft.AspNetCore.Mvc" />
|
||||||
|
<_MvcAssemblyName Include="Microsoft.AspNetCore.Mvc.Abstractions" />
|
||||||
|
<_MvcAssemblyName Include="Microsoft.AspNetCore.Mvc.ApiExplorer" />
|
||||||
|
<_MvcAssemblyName Include="Microsoft.AspNetCore.Mvc.Core" />
|
||||||
|
<_MvcAssemblyName Include="Microsoft.AspNetCore.Mvc.Cors" />
|
||||||
|
<_MvcAssemblyName Include="Microsoft.AspNetCore.Mvc.DataAnnotations" />
|
||||||
|
<_MvcAssemblyName Include="Microsoft.AspNetCore.Mvc.Formatters.Json" />
|
||||||
|
<_MvcAssemblyName Include="Microsoft.AspNetCore.Mvc.Formatters.Xml" />
|
||||||
|
<_MvcAssemblyName Include="Microsoft.AspNetCore.Mvc.Localization" />
|
||||||
|
<_MvcAssemblyName Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" />
|
||||||
|
<_MvcAssemblyName Include="Microsoft.AspNetCore.Mvc.Razor" />
|
||||||
|
<_MvcAssemblyName Include="Microsoft.AspNetCore.Mvc.RazorPages" />
|
||||||
|
<_MvcAssemblyName Include="Microsoft.AspNetCore.Mvc.TagHelpers" />
|
||||||
|
<_MvcAssemblyName Include="Microsoft.AspNetCore.Mvc.ViewFeatures" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<FindAssembliesWithReferencesTo Assemblies="@(ReferencePath)" TargetAssemblyNames="@(_MvcAssemblyName)">
|
||||||
|
<Output TaskParameter="ResolvedAssemblies" ItemName="_ApplicationPartAssemblyNames"/>
|
||||||
|
</FindAssembliesWithReferencesTo>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<_MvcApplicationPartAttribute Include="Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute">
|
||||||
|
<_Parameter1>%(_ApplicationPartAssemblyNames.Identity)</_Parameter1>
|
||||||
|
</_MvcApplicationPartAttribute>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- If we found application part assemblies, generate attributes for it and add it to compilation list -->
|
||||||
|
<WriteCodeFragment
|
||||||
|
AssemblyAttributes="@(_MvcApplicationPartAttribute)"
|
||||||
|
Language="$(Language)"
|
||||||
|
OutputFile="$(_MvcApplicationPartAttributeGeneratedFile)"
|
||||||
|
Condition="'@(_ApplicationPartAssemblyNames->Count())' != '0'" />
|
||||||
|
|
||||||
|
<ItemGroup Condition="'@(_ApplicationPartAssemblyNames->Count())' != '0'">
|
||||||
|
<Compile Remove="$(_MvcApplicationPartAttributeGeneratedFile)" Condition="'$(Language)'!='F#'" />
|
||||||
|
<Compile Include="$(_MvcApplicationPartAttributeGeneratedFile)" Condition="'$(Language)'!='F#'" />
|
||||||
|
|
||||||
|
<CompileBefore Remove="$(_MvcApplicationPartAttributeGeneratedFile)" Condition="'$(Language)'=='F#'" />
|
||||||
|
<CompileBefore Include="$(_MvcApplicationPartAttributeGeneratedFile)" Condition="'$(Language)'=='F#'" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
If we did not find any application parts, produce an empty file which is not added to compilation.
|
||||||
|
This is required to play nicely with incremental builds.
|
||||||
|
-->
|
||||||
|
<Touch
|
||||||
|
Files="$(_MvcApplicationPartAttributeGeneratedFile)"
|
||||||
|
AlwaysCreate="true" />
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<FileWrites Include="$(_MvcApplicationPartAttributeGeneratedFile)" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
|
|
@ -25,7 +25,7 @@ Copyright (c) .NET Foundation. All rights reserved.
|
||||||
<!-- Paths to tools, tasks, and extensions are calculated relative to the RazorSdkDirectoryRoot. This can be modified to test a local build. -->
|
<!-- Paths to tools, tasks, and extensions are calculated relative to the RazorSdkDirectoryRoot. This can be modified to test a local build. -->
|
||||||
<RazorSdkDirectoryRoot Condition="'$(RazorSdkDirectoryRoot)'==''">$(MSBuildThisFileDirectory)..\..\</RazorSdkDirectoryRoot>
|
<RazorSdkDirectoryRoot Condition="'$(RazorSdkDirectoryRoot)'==''">$(MSBuildThisFileDirectory)..\..\</RazorSdkDirectoryRoot>
|
||||||
<RazorSdkBuildTasksDirectoryRoot Condition="'$(RazorSdkBuildTasksDirectoryRoot)'==''">$(RazorSdkDirectoryRoot)tasks\</RazorSdkBuildTasksDirectoryRoot>
|
<RazorSdkBuildTasksDirectoryRoot Condition="'$(RazorSdkBuildTasksDirectoryRoot)'==''">$(RazorSdkDirectoryRoot)tasks\</RazorSdkBuildTasksDirectoryRoot>
|
||||||
<_RazorSdkTasksTFM Condition=" '$(MSBuildRuntimeType)' == 'Core'">netstandard2.0</_RazorSdkTasksTFM>
|
<_RazorSdkTasksTFM Condition=" '$(MSBuildRuntimeType)' == 'Core'">netcoreapp3.0</_RazorSdkTasksTFM>
|
||||||
<_RazorSdkTasksTFM Condition=" '$(_RazorSdkTasksTFM)' == ''">net46</_RazorSdkTasksTFM>
|
<_RazorSdkTasksTFM Condition=" '$(_RazorSdkTasksTFM)' == ''">net46</_RazorSdkTasksTFM>
|
||||||
<RazorSdkBuildTasksAssembly>$(RazorSdkBuildTasksDirectoryRoot)$(_RazorSdkTasksTFM)\Microsoft.NET.Sdk.Razor.Tasks.dll</RazorSdkBuildTasksAssembly>
|
<RazorSdkBuildTasksAssembly>$(RazorSdkBuildTasksDirectoryRoot)$(_RazorSdkTasksTFM)\Microsoft.NET.Sdk.Razor.Tasks.dll</RazorSdkBuildTasksAssembly>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
@ -335,6 +335,8 @@ Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
|
||||||
<Import Project="Microsoft.NET.Sdk.Razor.GenerateAssemblyInfo.targets" />
|
<Import Project="Microsoft.NET.Sdk.Razor.GenerateAssemblyInfo.targets" />
|
||||||
|
|
||||||
|
<Import Project="Microsoft.NET.Sdk.Razor.MvcApplicationPartsDiscovery.targets" Condition="'$(_TargetingNETCoreApp30OrLater)' == 'true'" />
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
These are the targets that actually do compilation using CSC, separated from the main file for ease of maintenance.
|
These are the targets that actually do compilation using CSC, separated from the main file for ease of maintenance.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
// 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.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
||||||
|
{
|
||||||
|
public class ApplicationPartDiscoveryIntegrationTest : MSBuildIntegrationTestBase, IClassFixture<BuildServerTestFixture>
|
||||||
|
{
|
||||||
|
public ApplicationPartDiscoveryIntegrationTest(BuildServerTestFixture buildServer)
|
||||||
|
: base(buildServer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[InitializeTestProject("AppWithP2PReference", additionalProjects: "ClassLibrary")]
|
||||||
|
public Task Build_ProjectWithDependencyThatReferencesMvc_AddsAttribute_WhenBuildingUsingDotnetMsbuild()
|
||||||
|
=> Build_ProjectWithDependencyThatReferencesMvc_AddsAttribute(MSBuildProcessKind.Dotnet);
|
||||||
|
|
||||||
|
[ConditionalFact]
|
||||||
|
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
||||||
|
[InitializeTestProject("AppWithP2PReference", additionalProjects: "ClassLibrary")]
|
||||||
|
public Task Build_ProjectWithDependencyThatReferencesMvc_AddsAttribute_WhenBuildingUsingDesktopMsbuild()
|
||||||
|
=> Build_ProjectWithDependencyThatReferencesMvc_AddsAttribute(MSBuildProcessKind.Desktop);
|
||||||
|
|
||||||
|
private async Task Build_ProjectWithDependencyThatReferencesMvc_AddsAttribute(MSBuildProcessKind msBuildProcessKind)
|
||||||
|
{
|
||||||
|
var result = await DotnetMSBuild("Build", msBuildProcessKind: msBuildProcessKind);
|
||||||
|
|
||||||
|
Assert.BuildPassed(result);
|
||||||
|
|
||||||
|
Assert.FileExists(result, IntermediateOutputPath, "AppWithP2PReference.MvcApplicationPartsAssemblyInfo.cs");
|
||||||
|
Assert.FileContains(result, Path.Combine(IntermediateOutputPath, "AppWithP2PReference.MvcApplicationPartsAssemblyInfo.cs"), "[assembly: Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute(\"ClassLibrary\")]");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[InitializeTestProject("SimpleMvc")]
|
||||||
|
public async Task Build_ProjectWithoutMvcReferencingDependencies_DoesNotGenerateAttribute()
|
||||||
|
{
|
||||||
|
var result = await DotnetMSBuild("Build");
|
||||||
|
|
||||||
|
Assert.BuildPassed(result);
|
||||||
|
|
||||||
|
Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.MvcApplicationPartsAssemblyInfo.cs");
|
||||||
|
// We should produced an empty file for build incrementalism
|
||||||
|
Assert.Empty(File.ReadAllText(Path.Combine(result.Project.DirectoryPath, IntermediateOutputPath, "SimpleMvc.MvcApplicationPartsAssemblyInfo.cs")));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[InitializeTestProject("AppWithP2PReference", additionalProjects: "ClassLibrary")]
|
||||||
|
public async Task BuildIncrementalism_WhenApplicationPartAttributeIsGenerated()
|
||||||
|
{
|
||||||
|
var result = await DotnetMSBuild("Build");
|
||||||
|
|
||||||
|
Assert.BuildPassed(result);
|
||||||
|
|
||||||
|
var generatedAttributeFile = Path.Combine(IntermediateOutputPath, "AppWithP2PReference.MvcApplicationPartsAssemblyInfo.cs");
|
||||||
|
Assert.FileExists(result, generatedAttributeFile);
|
||||||
|
Assert.FileContains(result, generatedAttributeFile, "[assembly: Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute(\"ClassLibrary\")]");
|
||||||
|
|
||||||
|
var thumbPrint = GetThumbPrint(generatedAttributeFile);
|
||||||
|
|
||||||
|
result = await DotnetMSBuild("Build");
|
||||||
|
|
||||||
|
Assert.BuildPassed(result);
|
||||||
|
|
||||||
|
Assert.FileExists(result, generatedAttributeFile);
|
||||||
|
Assert.Equal(thumbPrint, GetThumbPrint(generatedAttributeFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[InitializeTestProject("SimpleMvcFSharp", language: "F#", additionalProjects: "ClassLibrary")]
|
||||||
|
public async Task Build_ProjectWithDependencyThatReferencesMvc_AddsAttributeToNonCSharpProjects()
|
||||||
|
{
|
||||||
|
AddProjectFileContent(
|
||||||
|
@"
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include=""..\ClassLibrary\ClassLibrary.csproj"" />
|
||||||
|
</ItemGroup>
|
||||||
|
");
|
||||||
|
|
||||||
|
var result = await DotnetMSBuild("Build");
|
||||||
|
|
||||||
|
Assert.BuildPassed(result);
|
||||||
|
|
||||||
|
Assert.FileExists(result, IntermediateOutputPath, "SimpleMvcFSharp.MvcApplicationPartsAssemblyInfo.fs");
|
||||||
|
Assert.FileContains(result, Path.Combine(IntermediateOutputPath, "SimpleMvcFSharp.MvcApplicationPartsAssemblyInfo.fs"), "<assembly: Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute(\"ClassLibrary\")>");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[InitializeTestProject("SimpleMvc")]
|
||||||
|
public async Task BuildIncrementalism_WhenApplicationPartAttributeIsNotGenerated()
|
||||||
|
{
|
||||||
|
var result = await DotnetMSBuild("Build");
|
||||||
|
|
||||||
|
Assert.BuildPassed(result);
|
||||||
|
|
||||||
|
var generatedAttributeFile = Path.Combine(IntermediateOutputPath, "SimpleMvc.MvcApplicationPartsAssemblyInfo.cs");
|
||||||
|
Assert.FileExists(result, generatedAttributeFile);
|
||||||
|
Assert.Empty(File.ReadAllText(Path.Combine(result.Project.DirectoryPath, generatedAttributeFile)));
|
||||||
|
|
||||||
|
var thumbPrint = GetThumbPrint(generatedAttributeFile);
|
||||||
|
|
||||||
|
result = await DotnetMSBuild("Build");
|
||||||
|
|
||||||
|
Assert.BuildPassed(result);
|
||||||
|
|
||||||
|
Assert.FileExists(result, generatedAttributeFile);
|
||||||
|
Assert.Equal(thumbPrint, GetThumbPrint(generatedAttributeFile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -34,9 +34,9 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Razor.Tools\Microsoft.AspNetCore.Razor.Tools.csproj" />
|
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Razor.Tools\Microsoft.AspNetCore.Razor.Tools.csproj" />
|
||||||
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.csproj" />
|
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\Microsoft.NET.Sdk.Razor\Microsoft.NET.Sdk.Razor.csproj" />
|
||||||
|
|
||||||
<!-- We don't need anything in this assembly, we just want to make sure it's built -->
|
<!-- We don't need anything in this assembly, we just want to make sure it's built -->
|
||||||
<ProjectReference Include="..\..\src\Microsoft.NET.Sdk.Razor\Microsoft.NET.Sdk.Razor.csproj" ReferenceOutputAssembly="false" />
|
|
||||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Mvc.Razor.Extensions\Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj" ReferenceOutputAssembly="false" />
|
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Mvc.Razor.Extensions\Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj" ReferenceOutputAssembly="false" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,181 @@
|
||||||
|
// 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 Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.Tasks
|
||||||
|
{
|
||||||
|
public class ReferenceResolverTest
|
||||||
|
{
|
||||||
|
internal static readonly string[] MvcAssemblies = new[]
|
||||||
|
{
|
||||||
|
"Microsoft.AspNetCore.Mvc",
|
||||||
|
"Microsoft.AspNetCore.Mvc.Abstractions",
|
||||||
|
"Microsoft.AspNetCore.Mvc.ApiExplorer",
|
||||||
|
"Microsoft.AspNetCore.Mvc.Core",
|
||||||
|
"Microsoft.AspNetCore.Mvc.Cors",
|
||||||
|
"Microsoft.AspNetCore.Mvc.DataAnnotations",
|
||||||
|
"Microsoft.AspNetCore.Mvc.Formatters.Json",
|
||||||
|
"Microsoft.AspNetCore.Mvc.Formatters.Xml",
|
||||||
|
"Microsoft.AspNetCore.Mvc.Localization",
|
||||||
|
"Microsoft.AspNetCore.Mvc.NewtonsoftJson",
|
||||||
|
"Microsoft.AspNetCore.Mvc.Razor",
|
||||||
|
"Microsoft.AspNetCore.Mvc.RazorPages",
|
||||||
|
"Microsoft.AspNetCore.Mvc.TagHelpers",
|
||||||
|
"Microsoft.AspNetCore.Mvc.ViewFeatures",
|
||||||
|
};
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Resolve_ReturnsEmptySequence_IfNoAssemblyReferencesMvc()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var resolver = new TestReferencesToMvcResolver(new[]
|
||||||
|
{
|
||||||
|
CreateAssemblyItem("Microsoft.AspNetCore.Blazor"),
|
||||||
|
CreateAssemblyItem("Microsoft.AspNetCore.Components"),
|
||||||
|
CreateAssemblyItem("Microsoft.JSInterop"),
|
||||||
|
CreateAssemblyItem("System.Net.Http"),
|
||||||
|
CreateAssemblyItem("System.Runtime"),
|
||||||
|
});
|
||||||
|
|
||||||
|
resolver.Add("Microsoft.AspNetCore.Blazor", "Microsoft.AspNetCore.Components", "Microsoft.JSInterop");
|
||||||
|
resolver.Add("Microsoft.AspNetCore.Components", "Microsoft.JSInterop", "System.Net.Http", "System.Runtime");
|
||||||
|
resolver.Add("System.Net.Http", "System.Runtime");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var assemblies = resolver.ResolveAssemblies();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Empty(assemblies);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Resolve_ReturnsEmptySequence_IfNoDependencyReferencesMvc()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var resolver = new TestReferencesToMvcResolver(new[]
|
||||||
|
{
|
||||||
|
CreateAssemblyItem("MyApp.Models"),
|
||||||
|
CreateAssemblyItem("Microsoft.AspNetCore.Mvc", isSystemReference: true),
|
||||||
|
CreateAssemblyItem("Microsoft.AspNetCore.Hosting", isSystemReference: true),
|
||||||
|
CreateAssemblyItem("Microsoft.AspNetCore.HttpAbstractions", isSystemReference: true),
|
||||||
|
CreateAssemblyItem("Microsoft.AspNetCore.KestrelHttpServer", isSystemReference: true),
|
||||||
|
CreateAssemblyItem("Microsoft.AspNetCore.StaticFiles", isSystemReference: true),
|
||||||
|
CreateAssemblyItem("Microsoft.Extensions.Primitives", isSystemReference: true),
|
||||||
|
CreateAssemblyItem("System.Net.Http", isSystemReference: true),
|
||||||
|
CreateAssemblyItem("Microsoft.EntityFrameworkCore"),
|
||||||
|
});
|
||||||
|
|
||||||
|
resolver.Add("MyApp.Models", "Microsoft.EntityFrameworkCore");
|
||||||
|
resolver.Add("Microsoft.AspNetCore.Mvc", "Microsoft.AspNetCore.HttpAbstractions");
|
||||||
|
resolver.Add("Microsoft.AspNetCore.KestrelHttpServer", "Microsoft.AspNetCore.Hosting", "Microsoft.AspNetCore.HttpAbstractions");
|
||||||
|
resolver.Add("Microsoft.AspNetCore.StaticFiles", "Microsoft.AspNetCore.HttpAbstractions", "Microsoft.Extensions.Primitives");
|
||||||
|
resolver.Add("Microsoft.AspNetCore.Hosting", "Microsoft.AspNetCore.HttpAbstractions");
|
||||||
|
resolver.Add("Microsoft.AspNetCore.HttpAbstractions", "Microsoft.Extensions.Primitives");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var assemblies = resolver.ResolveAssemblies();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Empty(assemblies);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Resolve_ReturnsReferences_ThatReferenceMvc()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var resolver = new TestReferencesToMvcResolver(new[]
|
||||||
|
{
|
||||||
|
CreateAssemblyItem("Microsoft.AspNetCore.Mvc", isSystemReference: true),
|
||||||
|
CreateAssemblyItem("Microsoft.AspNetCore.Mvc.TagHelpers", isSystemReference: true),
|
||||||
|
CreateAssemblyItem("MyTagHelpers"),
|
||||||
|
CreateAssemblyItem("MyControllers"),
|
||||||
|
CreateAssemblyItem("MyApp.Models"),
|
||||||
|
CreateAssemblyItem("Microsoft.AspNetCore.Hosting", isSystemReference: true),
|
||||||
|
CreateAssemblyItem("Microsoft.AspNetCore.HttpAbstractions", isSystemReference: true),
|
||||||
|
CreateAssemblyItem("Microsoft.AspNetCore.KestrelHttpServer", isSystemReference: true),
|
||||||
|
CreateAssemblyItem("Microsoft.AspNetCore.StaticFiles", isSystemReference: true),
|
||||||
|
CreateAssemblyItem("Microsoft.Extensions.Primitives", isSystemReference: true),
|
||||||
|
CreateAssemblyItem("Microsoft.EntityFrameworkCore"),
|
||||||
|
});
|
||||||
|
|
||||||
|
resolver.Add("MyTagHelpers", "Microsoft.AspNetCore.Mvc.TagHelpers");
|
||||||
|
resolver.Add("MyControllers", "Microsoft.AspNetCore.Mvc");
|
||||||
|
resolver.Add("MyApp.Models", "Microsoft.EntityFrameworkCore");
|
||||||
|
resolver.Add("Microsoft.AspNetCore.Mvc", "Microsoft.AspNetCore.HttpAbstractions", "Microsoft.AspNetCore.Mvc.TagHelpers");
|
||||||
|
resolver.Add("Microsoft.AspNetCore.KestrelHttpServer", "Microsoft.AspNetCore.Hosting", "Microsoft.AspNetCore.HttpAbstractions");
|
||||||
|
resolver.Add("Microsoft.AspNetCore.StaticFiles", "Microsoft.AspNetCore.HttpAbstractions", "Microsoft.Extensions.Primitives");
|
||||||
|
resolver.Add("Microsoft.AspNetCore.Hosting", "Microsoft.AspNetCore.HttpAbstractions");
|
||||||
|
resolver.Add("Microsoft.AspNetCore.HttpAbstractions", "Microsoft.Extensions.Primitives");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var assemblies = resolver.ResolveAssemblies();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(new[] { "MyControllers", "MyTagHelpers" }, assemblies.OrderBy(a => a));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Resolve_ReturnsItemsThatTransitivelyReferenceMvc()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var resolver = new TestReferencesToMvcResolver(new[]
|
||||||
|
{
|
||||||
|
CreateAssemblyItem("MyCMS"),
|
||||||
|
CreateAssemblyItem("MyCMS.Core"),
|
||||||
|
CreateAssemblyItem("Microsoft.AspNetCore.Mvc.ViewFeatures", isSystemReference: true),
|
||||||
|
});
|
||||||
|
|
||||||
|
resolver.Add("MyCMS", "MyCMS.Core");
|
||||||
|
resolver.Add("MyCMS.Core", "Microsoft.AspNetCore.Mvc.ViewFeatures");
|
||||||
|
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var assemblies = resolver.ResolveAssemblies();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(new[] { "MyCMS", "MyCMS.Core" }, assemblies.OrderBy(a => a));
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssemblyItem CreateAssemblyItem(string name, bool isSystemReference = false)
|
||||||
|
{
|
||||||
|
return new AssemblyItem
|
||||||
|
{
|
||||||
|
AssemblyName = name,
|
||||||
|
IsSystemReference = isSystemReference,
|
||||||
|
Path = name,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestReferencesToMvcResolver : ReferenceResolver
|
||||||
|
{
|
||||||
|
private readonly Dictionary<string, List<ClassifiedAssemblyItem>> _references = new Dictionary<string, List<ClassifiedAssemblyItem>>();
|
||||||
|
private readonly Dictionary<string, ClassifiedAssemblyItem> _lookup;
|
||||||
|
|
||||||
|
public TestReferencesToMvcResolver(AssemblyItem[] referenceItems)
|
||||||
|
: base(MvcAssemblies, referenceItems)
|
||||||
|
{
|
||||||
|
_lookup = referenceItems.ToDictionary(r => r.AssemblyName, r => new ClassifiedAssemblyItem(r));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(string assembly, params string[] references)
|
||||||
|
{
|
||||||
|
var assemblyItems = references.Select(r => _lookup[r]).ToList();
|
||||||
|
_references[assembly] = assemblyItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IReadOnlyList<ClassifiedAssemblyItem> GetReferences(string file)
|
||||||
|
{
|
||||||
|
if (_references.TryGetValue(file, out var result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.Empty<ClassifiedAssemblyItem>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +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;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.ApplicationParts
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||||
|
public class ApplicationPartAttribute : Attribute
|
||||||
|
{
|
||||||
|
public ApplicationPartAttribute(string assemblyName) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -23,6 +23,11 @@
|
||||||
<UseRazorBuildServer>false</UseRazorBuildServer>
|
<UseRazorBuildServer>false</UseRazorBuildServer>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<!-- Have the SDK treat the MvcShim as an MVC assembly -->
|
||||||
|
<_MvcAssemblyName Include="Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<Import Project="After.Directory.Build.props" Condition="Exists('After.Directory.Build.props')" />
|
<Import Project="After.Directory.Build.props" Condition="Exists('After.Directory.Build.props')" />
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
-->
|
-->
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
|
<DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
|
||||||
<_ReferencesAspNetCoreApp>true</_ReferencesAspNetCoreApp>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue