Search code examples
.netnugetnuget-spec

.Net NuGet package conflicts - DLL Hell is back


I have a Visual Studio project.
It requires the Newtonsoft.Json library.
It is referenced with the NuGet package manager of Visual Studio 2017. Actually the version 10.0.3.

This project is referencing the NuGet package LibA and LibB.

LibA uses Newtonsoft.Json version 8 and this is defined in the package.nuspec:

<dependency id="RestSharp" version="105.2.3" />
<dependency id="Newtonsoft.Json" version="8.0.3" />
<dependency id="CommonServiceLocator" version="1.3" />

LibB uses NewtonSoft.Json version 10 and this is defined in the package.nuspec:

<dependency id="RestSharp" version="105.1" />
<dependency id="Newtonsoft.Json" version="10.0.3" />

When I update the LibA package (for example from version 1.1 to 1.2) using the NuGet Package Manager of Visual Studio 2017 (on the solution) it updates the reference of the LibA package as expected in the .csproj file:

 -  <HintPath>..\packages\LibA.1.1\lib\net40\MyService.dll</HintPath>
 +  <HintPath>..\packages\LibA.1.2\lib\net40\MyService.dll</HintPath>

but it also update the reference of the Newtonsoft.Json library:

-  <Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
-  <HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
+  <Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+  <HintPath>..\packages\LibA.1.2\lib\net40\\Newtonsoft.Json.dll</HintPath>

and the app/web.config file:

-  <bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
+  <bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />

It also update correctly the LibA reference in the package.config:

 -  <package id="LibA.MyService" version="1.1" targetFramework="net45" />
 +  <package id="LibA.MyService" version="1.2" targetFramework="net45" />

but it leaves the WRONG reference to the Newtonsoft.Json library version:

<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net47" />

I complain about 2 things:

  1. If I open the NuGet Package Manager it is showing that I'm using the Newtonsoft.Json version 10.0.3 in the current project:
    this is not true because when I build the solution in the bin folder it is stored version 8.0.3 and it is not possible to update the Newtonsoft.Json because it is "already" updated.
    Furthermore my project and the LibB that needs the vesion 10 are actually using version 8.

  2. I cannot decide to maintain the version 10 automatically, actually I have to merge and correct manually all the .config and .csproj files !

There is a way to avoid this nightmare?

Extra info.
The project and the LibB are set on .Net 4.7.
LibA is still on .Net 4.5.
LibA and LibB are deployed in the company NuGet repository.

[Update]
As suggested in the comments I'll try to NOT include the Newtonsoft.Json library in the LibA (and LibB) packages. Actually it happens because of this (I think):

  <files>
    <file src="bin\$configuration$\**\*.*" exclude="**\*.pdb" target="lib\net40"/>     
  </files>

I changed it to this:

<files>
    <file src="bin\$configuration$\**\MyCompany.*.*" exclude="**\*.pdb" target="lib\net40"/>     
</files>

and it works, the Newtonsoft.Json package is taken from NuGet.


Solution

  • Your first complaint is not correct. The NuGet Package Manager shows you what version of the NuGet package, not the version number embedded in the DLL. You could argue that the Package Manager should detect this, but it's really an edge case caused by a bad LibA package.

    You are correct about the fix: <file src="bin\$configuration$\**\*.*" exclude="**\*.pdb" target="lib\net40"/> should not be used.
    Ideally, you only include the assemblies produced by building the project. If you include dependencies, both internal (e.g. MyCompany.Common.dll) or external (e.g. OtherCompany.dll), you risk running into this problem. Put the dependencies on an internal NuGet server.