Search code examples
c#visual-studionugetnuspec

Erroneous dependency resolving for multi-targeting NuGet package


I am being confused by how dependencies are resolved when using a group-based dependency specification in NuGet.

I have a Visual Studio project targeting .NET Framework 4.6.1, with a NuGet dependency to a NuGet package (internal to my company):

This is in the packages.config file of my project:

<package id="Name.Of.My.Package" version="2.0.65" targetFramework="net461" />

And this is in the .csproj file:

<Reference Include="Name.Of.My.Package, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <HintPath>..\packages\Name.Of.My.Package.2.0.65\lib\net45\Name.Of.My.Package.dll</HintPath> </Reference>

That package is a multi-targeting package with a group-based dependency specification, which looks like this when I get it straight from the .nuspec file obtained by opening the packages\Name.Of.My.Package.nupkg file as an archive:

<dependencies> <group> <dependency id="Newtonsoft.Json" version="11.0.2" /> </group> <group targetFramework=".NETFramework4.0"> <dependency id="Microsoft.Bcl.Async" version="1.0.168" /> </group> </dependencies>

And the packages\Name.Of.My.Package\lib folder contains:

  • net40
  • net45
  • nestandard2.0

So my understanding here is that because my project is in net461, the reference should be added to the net45 version of my package (as seems to be the case if I look at the .csproj file), but more importantly that the only implicit dependency should be to Newtonsoft.

But this happens when I try to remove the Microsoft.Bcl.Async package in the package manager console:

Uninstall-Package Microsoft.Bcl.Async Attempting to gather dependency information for package 'Microsoft.Bcl.Async.1.0.168' with respect to project 'Name.Of.My.Project', targeting '.NETFramework,Version=v4.6.1' Resolving actions to uninstall package 'Microsoft.Bcl.Async.1.0.168' Uninstall-Package : Unable to uninstall 'Microsoft.Bcl.Async.1.0.168' because 'Name.Of.My.Package.2.0.65' depends on it.

This is happening in the latest version of Visual Studio 2017 (15.8.6).


Solution

  • Erroneous dependency resolving for multi-targeting NuGet package

    This is the correct behavior of nuget. As we know, .NET Frameworks are backwards compatible. Meaning if your project is targeting v4.6, you can consume packages with lower versions, such as v4.5, v4.0.

    NuGet's specialty is compatibility checking (if packages are authored correctly ofc) :) NuGet knows the available frameworks are v3.5, v4.0, v4.6 and netstandard1.3. The "nearest" compatible framework with v4.5 is v4.0, so it'll pick the v4.0 assets when you install it.

    Source: How to figure out the information of dependency packages for missing frameworks

    So nuget will install the dependence "nearest" backwards compatible framework v4.6.1, in you case, the dependency Microsoft.Bcl.Async will also be installed.

    That is the reason why you could not uninstall the package Microsoft.Bcl.Async when you have package Name.Of.My.Package installed.

    For example, when you add the package Microsoft.AspNet.WebApi.Client 5.2.6 to the .net framework 4.6.1 project, nuget will also add the dependency Newtonsoft.Json (>= 6.0.4) under the .net framework 4.5:

    enter image description here

    enter image description here

    Check this document for some more details.