14
votes

I have a .Net Framework 4.6.1 WPF project which references several .Net Standard 2.0 assemblies. Each of these assemblies has one or two dependencies of its own, pulled in from NuGet. When inside of Visual Studio, everything works and runs fine. However, when I first tried to publish the application and run it (on the same machine), I got this nasty Exception:

Could not load file or assembly 'System.Runtime, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.

After a couple of days of pulling my hair out, I finally discovered that adding the following binding redirect to my project's App.config solved the problem

<dependentAssembly>
  <assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
</dependentAssembly>

At least, it moved the problem to the System.ObjectModel. Then after I added a binding redirect for that, I got an error for System.Collections, and so on... before long, my App.config looked like this:

<dependentAssembly>
  <assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="System.ObjectModel" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="System.Collections" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="System.Reflection.Extensions" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="System.Reflection" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="System.Threading" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="System.Linq" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="System.Globalization" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="System.IO" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="System.Collections.Concurrent" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="System.Net.Requests" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="System.Net.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.0.11.0" newVersion="4.0.11.0" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="System.Text.RegularExpressions" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="System.Runtime.Extensions" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="System.Net.WebHeaderCollection" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="System.Runtime.InteropServices.RuntimeInformation" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>

Recently, I added the ServiceStack.Client.Core NuGet package to one of my .Net Standard Assemblies and added some code which makes calls to a web service. Again, everything worked great in Visual studio, but when I went to publish the app and then run, I started seeing these errors again whenever the app would try to call my web service. I started adding binding redirects until I came across an assembly that it seems to want two different versions of:

Could not load file or assembly 'System.IO.Compression, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' or one of its dependencies. The system cannot find the file specified

with the following inner exception:

Could not load file or assembly 'System.IO.Compression, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' or one of its dependencies. The system cannot find the file specified

If I try adding a binding redirect for 4.2.0.0, the outer exception goes away but I still see the exception for 4.1.1.0. I've tried adding a second binding redirect for 4.1.1.0 in just about every way I could think of (redirecting to 4.1.1.0, redirecting to 4.2.0.0, in the same <dependentAssembly> tag, in its own <dependentAssembly> tag, only having the 4.1.1.0 redirect... but no matter what I do, the inner exception persists. And yes, before you ask, I am aware that the publicKeyToken for this assembly is different from all the others.

As an additional note, I have found some StackOverflow posts which mention that adding <RestoreProjectStyle>PackageReference</RestoreProjectStyle> and/or <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> to my .csproj will solve these problems. I tried this but it did absolutely nothing whatsoever. Also, all of my projects use PackageReference and not packages.config

So, I have two questions:

  1. How the heck do I deal with this System.IO.Compression 4.2.0.0/4.1.1.0 dependency issue?
  2. Is there a better long-term solution to these problems? It feels very unmaintainable to me that any time I add a NuGet package to one of my .Net Standard libraries, I will get a bunch of runtime errors unless I go and manually add binding redirects for every single System.X dependency of the NuGet package.
1
Adding a NuGet package reference to ServiceStack.Client in the WPF project resolved my issue with System.IO.Compression. However, I tried doing the same with the other packages referenced by my .Net Standard libraries to see if this would allow me to remove the binding redirects I already have, but unfortunately I still seem to need them. So my immediate problem is resolved, but I'm still worried about maintainability.Katie
IMHO I think you got led down the wrong track. There is nothing wrong with using bindingredirects when dealing with nuget packages, but to do it for System.Runtime is unthinkable to me. I can think of two things, either all your projects aren't on the same runtime, or one of the installed nuget packages isn't. I would first make sure all the projects are on the same version. Then, check all your packages. If they aren't on the same version uninstall and reinstall it to see if it installs the correct version. If not, either you need to lower your version or find a new package.Taekahn
I'm bitten by a similar problem. Did you also upgrade to VS2017 15.5.1?Ziriax
@Katie assembly binding issues are hard to diagnose without the concrete application. It is likely that some NuGet package may be needed that somehow doesn't flow to the WPF project transitively across project-to-project references (likely for packages with different dependencies for different target frameworks). But without a sample app that reproduces your exact issue, this is impossible to diagnose.Martin Ullrich
@MartinUllrich here you go: github.com/kaitlynbrown/SystemRuntimeFailKatie

1 Answers

1
votes

I run into something similar. Although this is old post, here's what helped in my azure service fabric cluster binding problem:

  1. Switch to new project style
  2. Be sure to use .NET 4.6.1 for web projects. Use <PackageOutputFolder> true </PackageOutputFolder>. Taken from the bottom of this post.