27

I am a contributor to a GitHub project, and recently we had some trouble with our .NET Standard 2.0 project installing correctly into a .NET Framework 4.5 project. The cause of this is that (if I am understanding correctly) .NET Standard 2.0 supports a minimum .NET Framework of 4.6.1.

OK, fair enough. So we updated the .csproj to create another framework output:

<TargetFrameworks>netstandard2.0;net45</TargetFrameworks>

In our testing project, the supported frameworks are defined as such:

<TargetFrameworks>netcoreapp2.0;net471;net45</TargetFrameworks>

However, we are running into a problem with the net471 build as it seems to be picking up the net45 framework and not the netstandard2.0. In order to get this working, we are having to set the TargetFrameworks of the class library as such:

<TargetFrameworks>netstandard2.0;net471;net45</TargetFrameworks>

This seems excessive as it would seem that .netstandard2.0 should be the TargetFramework that net471 picks up, rather than the net45 target.

Is there a way to force a project reference to a particular TargetFramework? I did try the following in our testing project, but it did not seem work:

<ItemGroup Condition="'$(TargetFramework)' != 'net471'">
  <ProjectReference Include="..\..\src\ExtendedXmlSerializer\ExtendedXmlSerializer.csproj" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net471'">
  <ProjectReference Include="..\..\src\ExtendedXmlSerializer\ExtendedXmlSerializer.csproj">
    <TargetFramework>netstandard2.0</TargetFramework>
  </ProjectReference>
</ItemGroup>

Thank you in advance for any assistance you can provide!

Stephen Kennedy
  • 20,585
  • 22
  • 95
  • 108
Mike-E
  • 2,477
  • 3
  • 22
  • 34
  • It is by design for `net471` to pick up `net45`, and that also matches expectation. What's wrong with that? – Lex Li Jan 30 '18 at 17:04
  • @lex-li, since there is a `netstandard2.0` profile, and its minimum is 4.6.1, it would seem that a `net471` profile would select `netstandard2.0` since 4.6.1 is higher than 4.5? My understanding is that `netstandard2.0` is actually `net461` when bound to a .NET Framework-based application. So, it would seem that when given a `net471` application, `net461` would take precedence over `net45`. – Mike-E Jan 30 '18 at 20:43
  • 1
    that's a wrong assumption. As .NET Standard does not cover all .NET Framework API, you can easily found a NuGet package requiring it's .NET Framework consumers to stick to the .NET Framework specific assemblies. I am maintaining such as NuGet package, so I don't want the current behaviour to be changed in any way. – Lex Li Jan 30 '18 at 20:45
  • the "nearest TFM" selection logic always selects the same framework in a compatible version before falling back to compatible other frameworks. this has been this way before .net standard (e.g. PCLs). For project references, there's still msbuild tricks that can be used (see answer). it really is useful for tests projects in some situations. – Martin Ullrich Jan 30 '18 at 21:23
  • Ahhh... I am with you now. Even though .netstandard2.0 is technically 4.6.1, it doesn't start with a `net` moniker. `net45` is the only moniker available so it goes with this first. There really needs to be a way to configure (or define) a selection strategy. And by that I mean a little more elegant than hard coding TFM in obscure MSBuld-defined variables. ;) Anyways, thanks for your help, all! – Mike-E Jan 31 '18 at 07:50
  • Please change the accepted answer. [According to Microsoft](https://github.com/dotnet/sdk/issues/2280#issuecomment-605316016), Lorenzo's answer is the recommended solution. – NightOwl888 Mar 27 '20 at 21:13
  • 1
    Thank you @NightOwl888 I have done this and the more current solution is now marked as the answer. – Mike-E Mar 29 '20 at 09:58

2 Answers2

36

It does not work. VS 2017 15.5.5. Reference from 4.6.2 MSTest project net462 target of multitarget (net462;netstandard2.0) class library. – SerG Feb 13 at 13:34

It is true, the new way to solve that is this:

<ProjectReference Include="..\multitargeted_lib\multitargeted_lib.csproj">
  <SetTargetFramework>TargetFramework=netstandard2.0</SetTargetFramework>
</ProjectReference>

Source is here.

Unheilig
  • 16,196
  • 193
  • 68
  • 98
Lorenzo Isidori
  • 1,809
  • 2
  • 20
  • 31
30

Update 2020: The answer suggesting to use SetTargetFramework is a better fit, also to not conflict with other settings.

You can change your project reference like this:

  <ProjectReference Include="..\..\src\ExtendedXmlSerializer\ExtendedXmlSerializer.csproj" 
                    AdditionalProperties="TargetFramework=netstandard2.0" />

to force the selection of a specific target framework over the default "get nearest TFM" logic.

Martin Ullrich
  • 94,744
  • 25
  • 252
  • 217
  • 2
    WOOHOO! Thank you, Martin! Exactly what I was looking to do. Works perfectly. You = hero. :) Shout out to you here, my man: https://github.com/wojtpl2/ExtendedXmlSerializer/commit/14c7ee8c54f505e5f6c10d1a9043dd3edf24c806 – Mike-E Jan 31 '18 at 07:55
  • 2
    It does not work. VS 2017 15.5.5. Reference from 4.6.2 MSTest project net462 target of multitarget (net462;netstandard2.0) class library. – SerG Feb 13 '18 at 13:34