Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reproducing Newtonsoft.Json assembly version conflict

Tags:

c#

json.net

I've set out to consistently reproduce the assembly version conflict in Newtonsoft.Json (related to my previous question Why is Newtonsoft.Json so prone to assembly version conflicts?) in order to better understand it, but I can't trigger it.

From the top answer there, it should happen if I have project A which references one version of Json.NET, then it references a project B which itself references a different version (and they don't have assembly redirects to handle the issue).

I've made a solution with a Class Library project and a Command Line project, both of which reference Newtonsoft.Json which I installed with Nuget Package Manager for both projects, and then I edited the Class Library packages.config to use an older version:

<package id="Newtonsoft.Json" version="6.0.1" targetFramework="net452" />

While the Command Line project references the most recent version:

<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net452" />

This does not trigger the problem, however, the project still builds successfully and executes (I just serialize a string and print it from both projects, and I call the DLL from the EXE to ensure it tries to load both versions of Newtonsoft.Json.

I've uploaded the test project at https://github.com/sashoalm/ReproduceNewtonsoftJsonBug if needed.

Why isn't the bug getting triggered?

like image 397
sashoalm Avatar asked Jun 21 '17 11:06

sashoalm


1 Answers

First, despite what packages.json file says - your console application references version 6, not 10:

<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
  <HintPath>..\packages\Newtonsoft.Json.6.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>

However if you fix that (by uninstalling and reinstalling package for example) - it will still work fine. That is because there is automatic binding redirection in this case, see here:

Starting with Visual Studio 2013, new desktop apps that target the .NET Framework 4.5.1 use automatic binding redirection. This means that if two components reference different versions of the same strong-named assembly, the runtime automatically adds a binding redirection to the newer version of the assembly in the output app configuration (app.config) file.

If you look at output ConsoleApp5.exe.config file (not app.config in Visual Studio but in Debug\Release folder) - you will notice that binding redirects were automatically added there:

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
      <bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
    </dependentAssembly>
  </assemblyBinding>
</runtime>

If you remove them and then run target exe - it will fail at runtime.

That automatic binding redirecting is controlled by a property in .csproj file. If you open your console app .csproj you will see in one of the PropertyGroups:

<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>

If you change true to false - you will disable this feature and will see that warning you were trying to reproduce.

like image 172
Evk Avatar answered Oct 22 '22 02:10

Evk