Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Newtonsoft Json.NET version incompatibility (DLL hell)

Newtonsoft.Json release incompatible versions with same strong name, only changing the File version.

According to MSDN:

Assemblies that have the same strong name should be identical.

Because of this our application breaks if other applications, outside our control, put different version of Newtonsoft.Json.dll into the GAC.

Is there any way to force .NET to load a specific version we need?

Update:

Let me explain the problem more in depth:

In .NET, as far as I know, there is no mechanism to resolve assemblies before the CLR tries to resolve them and fails.

There is only the AppDomain.AssemblyResolve event and it fires only when the assembly is not resolved. Usually it is enough.

But in case with Newtonsoft.Json it does not fail to resolve the assembly but it simply loads the wrong one.

This happens because Newtonsoft.Json release incompatible versions with same strong name.

Example:

Let's say our application compiled against N.J.dll (assembly version 1.0, file version 1.0)

Then some other application, put other incompatible version of same dll into the GAC N.J.dll (assembly version 1.0, file version 1.1)

Because they only change file version and does not change assembly version, this two assemblies have the same strong name.

So for our application .NET trying to resolve N.J.dll (assembly version 1.0) it sees the dll in GAC and loads it. (Because .NET always prefer assembly from GAC for assembly from "bin" folder)

But assembly that loaded is wrong one. It has file version 1.1 and it is not compatible with version 1.0.

Because both assemblies has same assembly version, .NET does not see any difference beetween them. But then when it actualy try to resolve some class or member inside, it fails because it was changed in version 1.1.

And the whole application fails with unpredictable errors.

And the worst thing is that even if my application does not put newtonsoft.json.dll into the GAC, some other application, outside of my control, will put different version of newtonsoft.json.dll into GAC - my application will break with unpredictable exceptions.

So my question is, can I some how load correct assembly first, before .NET load wrong one?

Update

https://github.com/JamesNK/Newtonsoft.Json/issues/615 https://github.com/JamesNK/Newtonsoft.Json/issues/1001

Issues with this problem was closed with comment that show that the author of Newtonsoft.Json does not understand .NET versioning and why this is important.

like image 737
Yuri Bondarchuk Avatar asked Jul 24 '15 11:07

Yuri Bondarchuk


1 Answers

The assembly loader will only probe for missing assemblies, i.e. assemblies that are not already loaded. If you deploy the DLL to your application install folder then load it explicitly when your application starts up, then the assembly loader will not attempt to load it again from the GAC.

You can load the assembly explicitly using the Assembly.LoadFrom method.

See https://msdn.microsoft.com/en-us/library/dd153782(v=vs.110).aspx for more information.

like image 78
bikeman868 Avatar answered Oct 23 '22 19:10

bikeman868