35

In a large solution with 52 projects (all net462), the latest version of some of our dependencies are now only built for NET standard. Therefore they depend on the NuGet package NETStandard.Library which in turn drags in a lot of other 4.3.x version of System.* packages which are normally in the .NET Framework itself.

As a result, some projects reference System.* libraries from the packages folder, while others reference System.* libraries from the .NET Framework.

This causes the well-known runtime issue, f.e.:

Message: System.IO.FileLoadException : Could not load file or assembly 'System.Net.Http, Version=4.1.1.2, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

Digging into the dependencies of the NETStandard.Library packages, we can see that the same issue also exists in these packages:

  • System.Collections.*
  • System.ComponentModel.*
  • System.Console
  • System.Globalization.*
  • System.IO.*
  • System.Linq.*
  • System.Net.*
  • System.ObjectModel
  • System.Reflection.*
  • System.Resources.ResourceManager
  • System.Runtime.*
  • System.Text.*
  • System.Threading.*
  • System.Xml.*

Normally this is fixed by installing the same package in the other projects, but we're dealing with a lot of projects and a lot of packages here and I don't want to blindly add all of those dependencies to all 52 projects.

This made me wonder whether anyone knows of an easy way to recover from this situation and to make all projects reference the correct package/DLL from the NuGet packages folder if they currently use the NET Framework internal one.

A simple VS-solution for net462 and net471 demonstrating the problem can be found here

Will L
  • 557
  • 1
  • 7
  • 17
huysentruitw
  • 27,376
  • 9
  • 90
  • 133
  • 1
    For .NET Framework other than 4.7.1 and above, you have no option at all, but to do what you are doing now. 4.7.1 and above ships the shim assemblies by default, and you don't need to do that any more. More in https://blogs.msdn.microsoft.com/dotnet/2017/10/17/announcing-the-net-framework-4-7-1/ – Lex Li Jan 02 '18 at 15:58
  • 3
    4.7.1 still needs a few of these assemblies since there is a bug in 4.7.1 - it shipped with wrong assembly versions. – Martin Ullrich Jan 03 '18 at 00:08
  • @WouterHuysentruit, At this moment,it seems switch to latest framework 4.7.1 is a viable option. You can convert your comment to answer and accept it before you get a better solution, so it could help other community members who get the same issues. – Joy Jan 03 '18 at 09:03
  • 6
    Ah screw it. Updating Moq to 4.8.0 depends on `System.Threading.Tasks.Extensions 4.4.0` and now a lot of unit tests are throwing the FileLoadException for `System.Net.Http`. I'm about to burn this place down :p – huysentruitw Jan 03 '18 at 10:06
  • Had something similar a few times, usually the matching .net version is incorrect and/or the build order, might not be the case, but worth checking anyway. – Netferret Feb 06 '18 at 11:05
  • Could you post the contents of one of the `.csproj` files? Or better yet put all of them into a [Gist](https://gist.github.com/) and link to it? – NightOwl888 Feb 06 '18 at 18:43
  • Added a test for net462 and net471 [here](https://github.com/huysentruitw/test). Keep in mind that we're dealing with a lot of projects and a lot of possible conflicting references in the _real_ problem. – huysentruitw Feb 06 '18 at 19:12
  • Have you thought about writing a program or script that goes through your CSPROJ files and swaps ` – Josh E Feb 06 '18 at 19:44
  • I've run across problems with different `System.Net.Http` versions that adding a binding redirect wouldn't fix. I discovered that some projects sometimes only have a reference to this library but don't actually load it. I was able to fix the version problem by deleting the unneeded references (and any binding redirects) from those projects. I also needed to update the other projects that required `System.Net.Http` to the same version (added binding redirects where appropriate). – Sixto Saez Feb 06 '18 at 19:47
  • We used to delete references in order to avoid this problem, but this doesn't work anymore as we actually use them. The only fix I can currently think of is to add those 20+ depencencies to each project, which is a real bummer. – huysentruitw Feb 06 '18 at 21:27

1 Answers1

12

In the default project template System.Net.Http is added to the project as a reference, not as a nuget package.

In both of your solutions (4.6.1 and 4.7.1):

  • Project ClassLibrary has a dependency on System.Net.Http as a nuget package.

  • Project ConsoleApp1 has a dependency on System.Net.Http as a simple reference from .NET Framework

So, the issue is not related to Target Framework version.

To fix the issue add the same version of System.Net.Http as a nuget package to all projects (where it is used).

  1. Right-click the solution in Solution Explorer and choose Manage NuGet Packages for Solution...

  2. Switch to Installed tab

  3. Find System.Net.Http in the list, select it.

  4. Check current state:

Initial state of references to System.Net.Http nuget package

  1. Install the same version of the package (4.3.0 in your case) to ConsoleApp1 project.

  2. Check the result:

Fixed state of references to System.Net.Http nuget package

  1. Rebuild the solution.

Done.


Also, it's good practice to have package versions consolidated in your solution. Instead, you could have version conflicts during build time. Or, which is worse, runtime error like MethodNotFound because of binding redirect to another version of the dependency.


The reason for the problem with System.Net.Http is described here: Broken System.Net.Http 4.1.1-4.3.0 post-mortem in section How to prevent such situation in future? 2.1

As a result we identified 2 problematic OOB packages, which are not leaf-nodes in the platform itself, and have dependency from the platform on them - System.Net.Http and System.IO.Compression.

It means that the same System.Net.Http library is shipped within .NET Framework and as OOB (out-of-band) nuget package. And some nuget packages could reference nuget version of it. And here it comes the problem that I described at the very beginning.

So, you don't have to fix references to all System.* libraries. Only for these two: System.Net.Http and System.IO.Compression.

Will L
  • 557
  • 1
  • 7
  • 17
Vlad DX
  • 4,200
  • 19
  • 28
  • I'm not sure it's only those two packages. In our solution, the build generates warnings (assembly not found) for a lot of packages, like Microsoft.Win32, System.ValueTuple, etc... – huysentruitw Feb 10 '18 at 11:53
  • Other issues might be related to [this](https://github.com/dotnet/standard/issues/567). – huysentruitw Feb 12 '18 at 10:28
  • 1
    Helped me with the same problem, but with 'System.Threading.Tasks.Extensions' package – Vlad Jun 25 '18 at 05:42