Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The new DLL Hell; wrong assembly version being bound

I'm running VS2013 update 1 with Nuget v 2.8.50313.46

You can skip to this is the important bit, and some recent updates, and come back for reference.

I have a VS solution, this is a simplified representation of it.

-- Solution     - Base (Class Library)         Packages:             No Packages Installed.         References:             System             System.Configuration             System.Core             System.Runtime.Caching             System.Web      - AppBase (Class Library)         Packages:             No Packages Installed.         References:             System             System.Core             System.Web.Http             Base      - Client (Console Application)         Packages:             EntityFramework                v6.1.0             HtmlAgilityPack                v1.4.6         References:             EntityFramework             EntityFramework.SqlServer             HtmlAgilityPack             System             System.Core             AppBase             Base      - Server (Web Application)         Packages:             HtmlAgilityPack                v1.4.6             Microsoft.AspNet.WebApi        v5.1.2             Microsoft.AspNet.WebApi.Client v5.1.2                 (dependent on > Newtonsoft.Json v4.5.0)             Microsoft.AspNet.WebApi.Web... v5.1.2             Newtonsoft.Json                v6.0.3         References:             HtmlAgilityPack             Newtonsoft.Json             System             System.Net.Http             System.Net.Http.Formatting             System.Web             System.Web.Http             System.Web.HttpHost             AppBase             Base 

The code inside the Server needs Newtonsoft.Json v6.0.3 to function.

When I rebuild all and run everything works fine, as expected.

I subsequently build just AppBase, without building Server. AppBase is dependent only on Base. The binaries for AppBase and Base are "up-to-date", as expected.

However,

this is the important bit,

the building of AppBase causes the Newtonsoft.Json.dll in the "Server\bin" folder to be substituted for the earlier 4.5 version.

When I make a request to the Server, a "500 Intrernal Server Error" is returned due to the binding error caused by the incorrect Newtonsoft.Json dll version.

Why does building an assembly effect a non dependent assembly?

Has anybody else experienced this?

What is the best way to resolve this problem?


EDIT 19/06/2014

I made a new solution file, at first I thought this had resolved the problem. However the problem had transferred to the System.Net.Http.Formatting.dll :-S

If I edit AppBase so it does not reference System.Web.Http the effect goes away. Maybe this is something to do with the MVC stuff in Program Files? ...


EDIT 20/06/2014

I've posted a community wiki answer that details how I've worked around the problem. I thought somebody might find it useful. However, the workaround doesn't explain what mechanism is effecting Server when I build only AppBase and Base. Does this sound like a bug, it seems wrong?

like image 220
Jodrell Avatar asked Jun 19 '14 14:06

Jodrell


People also ask

How do you resolve DLL Hell?

Instead of picking from the system library, the compiler statically selects all DLL files from the application folder, implying that each program has its own library that is linked to the application. This solution fully eliminates the DLL hell issue.

What was the problem of DLL Hell in C#?

Dll Hell refers to a set of problems caused when multiple applications attempt to share a common component like a dynamic link library (DLL). The reason for this issue was that the version information about the different components of an application was not recorded by the system.

How does assembly versioning prevent DLL Hell?

NET prevent DLL Hell? - The runtime checks to see that only one version of an assembly is on the machine at any one time. - NET allows assemblies to specify the name AND the version of any assemblies they need to run.


2 Answers

The reference to System.Web.Http in AppBase was pointing to

C:\Program Files(x86)\Microsoft ASP.NET\ASP.NET MVC 4\Assemblies\System.Web.Http.dll

I added my latest

Microsoft.AspNet.WepApi.Core   5.1.2 

package to AppBase as used in Server. This pulled in the dependency packages,

Microsoft.AspNet.WebApi.Client 5.1.2 Newtonsoft.Json                6.0.3 (the only version in my package source) 

The System.Web.Http reference in AppBase now points to,

MySolutionFolder\packages\Microsoft.AspNet.WebApi.Core.5.1.2\lib\net45\System.Web.Http.dll

When I build AppBase now, the WepApi DLLs in Server no longer get altered to legacy versions.


Incidentally,

This package change adds multiple (a|A)pp.config files within the solution's projects, all with binding redirects to the latest version of Newtonsoft.Json.


Note

I actually view this as a work around albeit, one I'm glad to find.

The code in AppBase does not actually need the latest System.Web.Http.dll. I still don't know why building AppBase should effect Server, is this a bug?

Marking the troublesome DLLs as read-only did not protect them. Changing the security rights did, but no error was logged during the build of AppBase, even with diagnostic build logging.

like image 96
4 revs Avatar answered Sep 18 '22 22:09

4 revs


Nuget installs the selected package and any other packages it is dependent on. Obviously, in your Server solution there are packages using Newtonsoft.Json v4.5, so Nuget copies the dll to the bin, there is the problem occurs.

You may use binding redirect as Jon Skeet commented, or you should stick using Newtonsoft.Json v4.5 in Server solution.

Another option is using extern alias to reference two different versions of this dll.

like image 39
Artem Avatar answered Sep 18 '22 22:09

Artem