Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assembly mismatch despite having assembly redirect and loading correct version

My console app uses System.Net.Http.Formatting v5.1.0.0 that depends on Newtonsoft.Json v4.5.0.0. My app however includes v6.0.0.0 of Newtonsoft.Json (for other reasons).

To make System.Net.Http.Formatting use the new Newtonsoft.Json version I added an assembly redirect to the App.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
...
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" />
        <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0"/>
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

Still I get the following exception:

A first chance exception of type 'System.IO.FileLoadException' occurred in System.Net.Http.Formatting.dll

Additional information: Could not load file or assembly 'Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

The fusion log shows that the correct assembly is loaded but it fails because of mismatch:

*** Assembly Binder Log Entry  (2014.08.10. @ 13:13:25) ***

The operation failed.
Bind result: hr = 0x80131040. No description available.

Assembly manager loaded from:  C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable  D:\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe
--- A detailed error log follows. 

=== Pre-bind state information ===
LOG: DisplayName = Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
 (Fully-specified)
LOG: Appbase = file:///D:/ConsoleApplication1/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = ConsoleApplication1.exe
Calling assembly : System.Net.Http.Formatting, Version=5.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: D:\ConsoleApplication1\bin\Debug\ConsoleApplication1.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=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///D:/ConsoleApplication1/bin/Debug/Newtonsoft.Json.DLL.
LOG: Assembly download was successful. Attempting setup of file: D:\ConsoleApplication1\bin\Debug\Newtonsoft.Json.dll
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: Newtonsoft.Json, Version=6.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.

What can I do to resolve this mismatch? Thanks in advance.

Solution

There was nothing wrong with the redirect. The only clue was that it somehow didn't even get applied, although seemingly everything worked as expected (note that the log even shows that the correct config file is loaded). The issue was that there was this declaration in the assemblyBinding section for another assembly issue:

<qualifyAssembly partialName="log4net" fullName="log4net, 1.2.13.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a" />

This line solved that other issue but somehow broke the Json redirect. I don't know why: the qualifyAssembly declaration is supposedly correct too.

Nevertheless removing this declaration made the assembly redirect work...

like image 598
Piedone Avatar asked Aug 10 '14 11:08

Piedone


2 Answers

Just wanted to add a small amount of additional detail here, since this is a particularly nasty problem and garlic, silver bullets, and holy water are in short supply.

We ran into this recently and discovered that the cause was schema-violating XML in the app.config resulting from a bad auto-merge, e.g.

<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" />
        <assemblyIdentity name="Microsoft.Extensions.FileProviders.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-1.1.1.0" newVersion="1.1.1.0" />
</dependentAssembly>

We didn't notice the problem in the file since it's still technically valid XML and the Visual Studio parser never complained.

The runtime binding routine, however, refused to apply any of the binding redirects (even ones stated outside of the malformed section). Furthermore, as alluded to above, there is no indication in the fusion logs that the runtime failed to parse the config file. It sees the correct dlls and config file location but still fails with a minor version discrepancy as if there was never any redirect applied.

TL;DR - If you're getting this behavior, check to see that your config file XML is 100% perfect -- and don't trust that the squiggly lines in VS will reveal every possible problem.

like image 94
silijon Avatar answered Oct 20 '22 20:10

silijon


There is no evidence that your <bindingRedirect> is in effect. You should see:

LOG: Redirect found in application configuration file: 4.5.0.0 redirected to 6.0.0.0.
LOG: Post-policy reference: Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed

There are no breadcrumbs in your question, but whatever you edited appeared to not have been D:\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe.Config. Odd drive letter. Beware of a project already having an App.config project item and you adding App1.config. Something like that.

like image 32
Hans Passant Avatar answered Oct 20 '22 20:10

Hans Passant