This runtime exception is more prone to occur when we use different versions of the same assembly. As long as the new assembly version is backward compatible, the issue can be easily fixed.
Let’s first examine how runtime finds the assembly before discussing how to fix this problem. You can skip this section if all you want to know is the answer, but reading it through once will help you understand why this exception occurs.
How Run-time locates assembly
Imagine the following situation: I am utilizing Newtonsoft.Json in my project. Additionally, I’m mentioning a library that makes use of Newtonsoft.JSON, albeit in a distinct version. One Newtonsoft.JSON.dll may be present in the bin/debug or bin/release folders after the solution has been built.
Run the assembly binding log viewer, fuslogvw.exe, from the developers command prompt with administrator rights. It comes installed with Visual Studio. Navigate to the project’s debug (bin) directory.
This is an example probing log (bold text indicates relevant sections):
LOG: This bind starts in default load context. LOG: Using application configuration file: F:\visual studio 2017\Projects\TestBindingApp\TestBindingApp\bin\Debug\TestBindingApp.exe.Config LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. LOG: Post-policy reference: Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed LOG: GAC Lookup was unsuccessful. LOG: Attempting download of new URL file:///F:/visual studio 2017/Projects/TestBindingApp/TestBindingApp/bin/Debug/Newtonsoft.Json.DLL. LOG: Assembly download was successful. Attempting setup of file: F:\visual studio 2017\Projects\TestBindingApp\TestBindingApp\bin\Debug\Newtonsoft.Json.dll LOG: Entering run-from-source setup phase. LOG: Assembly Name is: Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed WRN: Comparing the assembly name resulted in the mismatch: Major Version ERR: The assembly reference did not match the assembly definition found. ERR: Run-from-source setup phase failed with hr = 0x80131040. ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated
This log provides information about the location of assembly. Further information can be found at Microsoft Docs — How runtime finds the assembly. Here is a synopsis:
- Determine the correct assembly version: app/web config, publisher policy and machine.config are examined for this.
- Cached Assembly: If the same assembly bound was checked before being used, the current request is immediately rejected without further action.
- GAC: Assembly is checked in Global Assembly Cache, it must be strongly named.
- Code base or Probing: The <codeBase> element’s location is checked first. If not, probing is carried out in application base taking into account the element’s name, culture, and private path. When an executable is run, the application base is the location.
And so the question arises: Why can’t an assembly error be loaded? One of the initial steps is where it is failing. The assembly matching the version is typically not found in the first step.
Think about the following situation:
Lib A references Lib C v1
Lib B references Lib C v2
Lib A references Lib B
Once the project is built, there will only be one version of Lib C in the application base, making it impossible for Lib A to locate other versions.
Which version of Lib C would be in the Application base, do you suppose?
It is Lib C v1. The reason is dependency resolver follows 4 rules
Lowest applicable version (e.g. Version 2.2 for ≥2.2 and if 2.2 is not available and 2.3 is next then 2.3)
Wildcard (e.g. 2.3.9 for 2.3.* — latest 2.3.x version)
Nearest wins (as in this scenario — Lib C v1 directly referenced by Lib A. Thus, this rule can result in a downgrade of the package version)
Cousin dependency (minimum version that meets all specifications). This occurs when various package versions are shown in the graph as being the same distance from the application. For instance, Lib A refers to Lib B1 & Lib B2. B1 and B2 each refer to a distinct version of Lib C.
We comprehended which version the program receives and how runtime inspects it. Let’s now investigate potential fixes.
Solution
There are two solutions:
- Upgrade NuGet package of Lib C in Lib A to v2
- Adding binding Redirect element in config file
Let’s see binding redirect solution first.
Binding Redirect:
The fix is easy —add <bindingRedirect> element in app.config or web.config. Below is sample fix for above log:
<runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <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> </assemblyBinding> </runtime>
This indicates which assembly version should be used in place of the previous one. An earlier version can also be provided in newVersion; a later version need not always be specified in newVersion. Thus, in this case, it would now search for version 11 of Newtonsoft.JSON for any assembly reference that contained it.
Keep in mind that a security permission is needed for explicit assembly binding redirection in an application configuration file.
In the case of Lib C, it is preferable to simply update the NuGet package of Lib C in A to v2 because Lib C v1 is less than Lib C v2, which means that when that lib is attempted to load while executing code in Lib B (Lib B requires Lib C v2).
Update NuGet Package:
Therefore, updating the NuGet package in every root project and, if necessary, in each subsequently referred project where the same package is referred to is another way to solve the problem.
Conclusion
I hope it was helpful in deciphering the mechanism and fixing the mistake. Thank you for reading, and if you liked it, please feel free to share this article.
If you are looking for fast and secure ASP.NET hosting, you can visit our site at https://www.asphostportal.com. Our fully featured hosting already includes
- Easy setup
- 24/7/365 technical support
- Top level speed and security
- Super cache server performance to increase your website speed
- Top 9 data centers across the world that you can choose.
Andriy Kravets is writer and experience .NET developer and like .NET for regular development. He likes to build cross-platform libraries/software with .NET.