runtime: NuGet adds wrong binding redirects with .NET 4.7.2
This issue was created because of a discussion on twitter @karelz & @joperezr.
We have a pretty large (+100 proj) solution that we are develop for the past 6-7 years with different Visual Studio versions etc. Last week I was trying to update our solution from .NET Framework 4.5.2 to 4.7.2 and I tried to updated the most important NuGet packages as well. Sadly I ended up with some pretty strange binding redirects in more or less all app.configs in our whole solution.
I could not easily reproduce the exact issue when I created a simple sample, but I was able to cut out one project from our solution, which behaves strange.
Sample Repo: https://github.com/Code-Inside/Samples/tree/master/2018/Net472WrongBindings
The “OneOffixx.Service.Host” project is a pretty old one and it also referenced a nuget.target file in the csproj. I’m not sure why we still have those .target files in place, but this was OK-ish some years ok.
Keep in mind: The project targets .NET Framework 4.5.2 and has the following binding redirect:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="WindowsBase" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="EntityFramework" publicKeyToken="b77a5c561934e089" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Practices.Prism" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
To reproduce the issue I updated the target version to 4.7.2 and clicked the update all package button on the NuGet Client UI.
After the package installations I got this redirect configuration:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="WindowsBase" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="EntityFramework" publicKeyToken="b77a5c561934e089" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Practices.Prism" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
</dependentAssembly>
<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.Diagnostics.Tracing" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.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>
</assemblyBinding>
</runtime>
With this configuration my application won’t start because either System.Runtime.dll is missing or System.Net.Http.dll is missing. When I remove those entries it seems fine. Im my real solution there were some other problematic redirects as well and I needed to clean them manually, but I’m not sure what causes this.
I was unable to reproduce the issue with newer projects - maybe it has something todo with the targets file? Sometimes when I update one nuget package I got some very strange binding redirects automatically injected in each web or app.config.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 1
- Comments: 17 (9 by maintainers)
That is correct, unfortunately not all projects in VS have the automated way of converting from packages.config into PackageReference. That said, you can still do it manually yourself, and it should work fine by taking a look into your packages.config, and for every entry there, adding one in your .csproj like the following:
Entry in packages.config:
New entry to add manually on your .csproj:
Finally just Remove all of the automatic references that where added by the packages.config (they are easy to spot as the HintPath on the reference will point to your NuGet packages folder)
I know it’s not ideal, (and I would suggest adding if possible an issue through VS Feedback) but it is a process that you only have to go through once and it will remove most of the problems around binding redirects and missing assemblies.
what seems to be happening here, is that you are still using the packages.config model for NuGet references, which is why NuGet is adding the Binding redirects at install time. This logic is faulted in many cases and legacy, and the new way to generate the binding redirects is at build time, and in order to use this, you need to migrate your project to use PackageReference instead. Once you do that, your App.config should have no binding redirects at all, and (if you have autogeneratebindingredirects turned on) our build targets will calculate the right binding redirects that you will need at runtime, and generate these binding redirects in your config file that gets dropped into your bin folder. This logic has way more knowledge about your references and dependencies, so the calculation of those binding redirects will be much better than the one NuGet does in the legacy packages.config world. So in summary, migrating to PackageReference and enable auto binding redirects should fix your issue.
@joperezr
PackageReference isn’t available for all project types yet. We have this problem frequently on our WPF projects (Install-Package always adds references to an incompatible version of System.Runtime for projects targeting 4.7.2) and we have to manually revert the app.config changes so that the framework implementation is used.