14

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.
Katie
  • 1,498
  • 1
  • 15
  • 33
  • 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 Dec 08 '17 at 00:31
  • IMHO I think you got led down the wrong track. There is nothing wrong with using `bindingredirect`s 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 Dec 09 '17 at 01:44
  • 1
    I'm bitten by a similar problem. Did you also upgrade to VS2017 15.5.1? – Ziriax Dec 09 '17 at 14:19
  • @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 Dec 09 '17 at 21:28
  • @MartinUllrich here you go: https://github.com/kaitlynbrown/SystemRuntimeFail – Katie Dec 09 '17 at 21:52
  • @Katie this example project runs fine when built with VS 2017 15.5.1 (I just had to add a temporary key file - don't have older VS versions to compare now) – Martin Ullrich Dec 10 '17 at 01:30
  • @MartinUllrich that's because it has the binding redirect added for System.Runtime. If you check out the first commit, you can see the failure. – Katie Dec 10 '17 at 02:41
  • Hate to say it but "works on my machine" even with all binding redirects removed from app.config and removed netstandard.library package. I used VS 2017 15.5.1 and windows 10 1709 using .net framework 4.7.1 which may also contribute to the behaviour of the issue. – Martin Ullrich Dec 10 '17 at 14:41
  • @MartinUllrich when you say it "works on your machine" do you mean it runs? Because that was never the problem. As I mention in the original post, it runs fine within visual studio and that is not the problem. The problem is when I try to publish the application, then install and run the published app. I have tried building and publishing on two different machines with the same result. – Katie Dec 10 '17 at 17:32
  • Now the problem is even worse. After adding a reference to the NuGet package `System.ComponentModel.Annotations` in one of my libraries, I get the error with the `System.ComponentModel.Annotations` assembly. I tried binding redirects and still get the error. I tried adding the same NuGet package to my WPF assembly and still got the error. Now I'm at a loss for what to do. This is getting to be extremely frustrating. – Katie Dec 13 '17 at 21:11
  • If anybody ends up here via a search, update to 4.7.2 and nuke all your binding redirects (you may have to add some back in so just comment them out :/). Here's the deets: https://github.com/Microsoft/dotnet/blob/master/releases/net471/KnownIssues/514195-Targeting%20.NET%20Framework%204.7.1%20copies%20extra%20files%20to%20your%20bin%20directory.md and FYI this was caused by 4.6.1 supporting netstandard. They had a number of assemblies that were kinda screwed up and yadda yadda this is the mess we've had to deal with. –  Sep 28 '18 at 19:51
  • If someone lands here then the article you want to read on binding redirects is this https://nickcraver.com/blog/2020/02/11/binding-redirects/ – James Westgate Feb 08 '23 at 22:00

1 Answers1

1

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.
Geralt
  • 142
  • 1
  • 8