Use latest version of System.Net.Http in .Net Framework
.NET can be very painful to develop as new versions of System packages are released, and you happen to use a library that adopts the new version. The new versions contains some additional APIs that the library uses, and if you use an older one, your program may still run, but crash at run time with MethodNotFoundException
because the older DLL doesn't contain a particular method defined.
Even when you ship the latest version, you can still have a problem. For instance, one library uses System.Net.Http 4.2.0.0 another uses System.Net.Http 4.3.0.0, and you ship 4.3.0.0 with the application, the library that uses 4.2.0.0 will look for exactly version 4.2.0.0, and crash your program since you didn't have the same version included. The .NET team anticipated this and allow your program to redirect 4.2.0.0 to 4.3.0.0, this is known as a binding redirect.
Once you have a lot of binding redirects, it's impossible to manage by hand.
The best way is to have the computer do this automatically for you. Update the .csproj
file so it contains an AutoGenerateBindingRedirects
tag.
<Project>
<PropertyGroup>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
</Project>
Next, update your app.config
or web.config
and remove all binding redirects
<configuration>
<runtime>
<!-- REMOVE THE ENTIRE SECTION START -->
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
</dependentAssembly>
</assemblyBinding>
<!-- REMOVE ENTIRE SECTION END -->
</runtime>
</configuration>
When you build the application, and you inspect the bin\Debug\YOURAPP.exe.config
you will find binding redirects has been added automatically so that all the libraries look for a single version of a DLL.
Additional steps for Web Applications
If you have a web.config
, then the process is different. Since Web.config needs to be shipped to the production machine, it needs the correct assembly binding redirect added. Visual Studio will compute the assembly binding redirects required, and show a build warning.
When you double click on the build warning, the correct assembly binding redirect will be added to your web.config.
Additional checks
If you use packages.config
, then you should check that your .csproj
is referencing the same versions of nuget defined in the packages.config
.
However, if you are building an .exe, and not a web application, I recommend you convert your project to use PackageReference instead. Visual Studio will ensure the same version is referenced automatically and you will not have to check.
Totally agree with you that this is confusing, but at the end binding redirection is your friend here used with your app.config / web.config file.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<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>
</assemblyBinding>
</runtime>
</configuration>
The above snippet forces whatever version comes in with your code that the version which is specified in "newVersion" attribute will be used.
The table below gives you some insights on the versioning differences.
Some info on the binding redirection by Microsoft itself.
I have several projects where I was forced to install .NETStandard 2.0 because some other package was dependent on it, even though we're just using .NET 4.6.1. After a long time Googling (and sorry, I can't point you to where I found this because it was done so long ago), I was able to figure out that when you have packages that are using the netstandard2 version of the assemblies, VS will automatically force System.Net.Http
to version 4.2.0, even if you don't have the binding redirect as explained by Dimi. Packages that install themselves with netstandard2 include System.Buffers
, System.Collections.Immutable
, System.Memory
, System.Runtime.Compilers.Unsafe
, and System.Text.Encodings.Web
(I'm sure there are more).
What I ended up having to do was manually edit the .csproj files and force these assemblies to use the netstandard1.x versions.
<Reference Include="System.Memory, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Memory.4.5.1\lib\netstandard2.0\System.Memory.dll</HintPath>
</Reference>
So for example, the hint path for System.Memory
points to the netstandard2.0
folder. If you go to your packages folder for, you'll find that there are three flavors of this assembly: netcoreapp211
, netstandard1.1
, and netstandard2.0
. I don't want the first one because I'm not using .NET Core, so I changed it to use 1.1 instead. After doing that for all assemblies that point to netstandard2.0
to 1.0 or 1.1 (whichever is available), VS then allowed me to use the System.Net.Http.4.3.4
package that I actually had installed.
I really don't know why this works, as I know almost nothing about .NETStandard, but it does.