Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Force PackageReference to target a specific TFM #13554

Closed
jzabroski opened this issue Jun 17, 2024 · 3 comments
Closed

Force PackageReference to target a specific TFM #13554

jzabroski opened this issue Jun 17, 2024 · 3 comments

Comments

@jzabroski
Copy link

jzabroski commented Jun 17, 2024

@zivkan Is there a way to force PackageReference to target a specific TFM? As an alternative (and improvement) to AssetTargetFallback.

I think there is a design flaw/bug in how nuget transitive restore works in the case of net48 projects that reference a package that targets netstandard2.0 that transitively references a package that targets both netstandard2.0 and net462.

In my case, System.Diagnostics.DiagnosticSource is a messy nuget package that claims to support net462, except .NET Framework 4.6.2 does not have the Logger field, so telemetry packages emit a ton of the same repeat message: "The parameters to the Event method do not match the parameters to the WriteEvent method. This may cause the event to be displayed incorrectly." I'd love to tell my ASP.NET Classic Website that targets net48 to fallback to netstandard2.0 for just this package.

The crux of the problem appears to be GetReferenceNearestTargetFrameworkTask assumes I want net462 rather than netstandard2.0, but I'm not certain!

The following does not seem to work, because the first pass finds net462 (when almost everyone expects a net48 project to use netstandard2.0 if available):

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <AssemblyTitle>My.Web</AssemblyTitle>
    <TargetFramework>net48</TargetFramework>
    <IsPackable>false</IsPackable>
  </PropertyGroup>

  <PropertyGroup>
    <AssetTargetFallback>netstandard2.0;$(AssetTargetFallback)</AssetTargetFallback>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Autofac.Mvc5" Version="6.1.0" />
    <!-- This Autofac.Web package references System.Diagnostics.DiagnosticSource 7.0.2 -->
    <PackageReference Include="Autofac.Web" version="7.0.0" />
    <!--10.x is the last version that supports .NET Framework -->
    <PackageReference Include="AutoMapper" Version="[10.1.1,11.0.0)" />
    <!-- 4.x is the last version that supports .NET Framework -->
    <PackageReference Include="AutoMapper.Extensions.ExpressionMapping" Version="[4.1.5,5.0.0)" />
    <PackageReference Include="Microsoft.AspNet.Mvc" Version="5.3.0" />
  </ItemGroup>
</Project>

I think the problem is that .NETCoreApp (.NET Core and .NET 5+) is not directly compatible with .NET Framework. The .NET SDK defines asset target fallback. However, since NuGet finds that netstandard2.1 asset, asset target fallback is not used, hence the .NET Framework runtime asset is NOT compatible. Your package needs netstandard2.1 runtime assets.

To see AssetTargetFallback in action, you need a package with only .NET Framework assets, then reference the package from a project targeting .NET Framework. NuGet will raise a warning that the package was used, but might not be fully compatible, because there are bunch of .NET Framework APIs that don't work on .NET (Core), and if the package uses any of those APIs, the app will crash at runtime, which is basically what different TFM versions and TFM compatibility is trying to avoid.

But to reiterate the point, in order to reenforce its understanding, Asset Target Fallback works in two passes. First, NuGet attempts to do asset selection without any asset target fallback. if any assets match, from any asset class (compile, runtime, content files, build) finds a compatible asset, then asset target fallback will NOT be used. Only when NONE of the asset classes find any matches, then NuGet will try asset target fallback.

Therefore, projects that are compatible with .NET Standard 2.1, they will not select .NET Framework assets in a different asset class. This is by design because .NET Framework and .NET Core App are not "guaranteed" to be compatible. In fact, there are known API and runtime differences.

Originally posted by @zivkan in #12972 (comment)

Copy link
Contributor

Issue is missing Type label, remember to add a Type label

@dotnet-policy-service dotnet-policy-service bot added the missing-required-type The required type label is missing. label Jun 17, 2024
@nkolev92
Copy link
Member

@nkolev92 nkolev92 closed this as not planned Won't fix, can't repro, duplicate, stale Jun 17, 2024
Copy link
Contributor

no assignees Issue is missing Type label, remember to add a Type label

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants