Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding Redirect Hell

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.
like image 328
Katie Avatar asked Dec 07 '17 23:12

Katie


People also ask

What is a binding redirect?

Rely on 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.

What is auto generate binding redirects?

Binding redirects are added if your app or its components reference more than one version of the same assembly, even if you manually specify binding redirects in the configuration file for your app. The automatic binding redirection feature affects desktop apps that target . NET Framework 4.5. 1 or a later version.


1 Answers

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.
like image 184
Geralt Avatar answered Oct 17 '22 14:10

Geralt