Troubleshooting NuGet references

Damir Dobric Posts

Next talks:

 

    

Follow me on Twitter: #ddobric



 

 

Archives

When working with NUGET in big projects (just a bit bigger than default hello-world) you might run into following issue:

Could not load file or assembly ‘…’

The prominent of this error example is :Could not load file or assembly 'Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The system cannot find the file specified.

This very simple error message can be caused by a number of different reasons. In this article I will try to put together all issues and solutions which I found.

 

1. Incorrect assembly loaded

Typically one assembly cannot be loaded, because it is not referenced at all. Assuming that this is very trivial issue, you have probably referenced it.
Unfortunately some other component referenced from your project (i.e. Http.Formatting.Dll) can als reference the same assembly, but different version.

For example, your the required version is defined by NuGet in packages file as follows:

  <package id="Newtonsoft.Json" version="6.0.0.0" targetFramework="net451" />

But this does not means, that all other assemblies will try to load exactly this version of the assembly.
(Before you proceed have to first enable Fusion Log to get all binding failures).
If you did it, you will get following more descriptive error:

=== Pre-bind state information === LOG: DisplayName = Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed (Fully-specified) LOG: Appbase = file:///C:/Tfs/Hyperion/Homag/ProFuture/CoreServices/Homag.ProFuture.GenericIDocHandler.Service/ LOG: Initial PrivatePath = C:\Tfs\Hyperion\Homag\ProFuture\CoreServices\Homag.ProFuture.GenericIDocHandler.Service\bin
Calling assembly : System.Net.Http.Formatting, Version=5.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35. ===

Please lookup a word: “Calling” to figure out which assembly is trying to load incorrect version. In this case it is System.Net.Http.Formatting. That assembly is trying to load System.Net.Http.Formatting, although you have referenced some higher (or even older) version. The problem is that only one version of the same assembly can be loaded in domain. In this case, your application has loaded v5.2 (specified in packages file) version of Newtonsoft.Json , but Http.Formatting assembly will version 4.5.

To workaround this we need to define assembly binding redirect in web.config (app.config).

<runtime>

    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
      </dependentAssembly>

</runtime>

This will enforce loading of v6.0.0.0 for all requests of any version of the Newtonsoft.Json assembly.

2. Version mismatch between NuGet and Assembly

If you already did everything as described in step 1, and if you till get the same error. In this case it could be that the NuGet version does not match the version of assembly.
For example, packages file can request assembly as follows:

  <package id="Newtonsoft.Json" version="6.0.4" targetFramework="net451" />

If you have defined redirect in your config file to load the correct version you will do following:

        <bindingRedirect oldVersion="0.0.0.0-6.0.4" newVersion="6.0.4" />

In this case you have defined everything correctly, but it still does not work, it is most likely that you have a version mismatch problem.
For example NuGet requires v6.4, but assembly version is v6.0 (stored in metadata, explorer does not necessarily helps to see this mismatch).

To fix this you would put in config file following :

  <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />

Note, assembly loader doe not know anything about nuget. It loads the version as specified in config-file as long this version mathes physically stored metadata.

 

3. Incorrect assembly referenced

Sometimes when working on different machines or in different workspaces or when you move project in TFS form one location to another one it can happen that incorrect assemblies are referenced.
For example, packages file specifies version 6.0.4 of Newtonsoft.Json.
In this case the reference to that assembly should be something like “C:\Tfs\MyProject\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll”.
Unfortunately you can figure out that this is not the case. In this case the reference will be typically like: “c:\program files86\referencedassemblies\Newtonsoft.Json.dll”

Basically this means, that this is incorrect version. VS has referenced the default version, because the right one was not found.

If the right version was not found it can be that it does not exist on the disk or it is on different location.
- If it does not exist on the disk 
go to Package Manager Console and you will see this:

image

Click on Restore and package will be downloaded. In this case reference will not be automatically repaired. So, you have to go to references, remove existing
reference (c:\program files86\referencedassemblies\..) and add the correct one C:\Tfs\MyProject\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll.)

- If it on on different location

you will also have to reference it as describe before. Remove existing reference and add correct one.
Unfortunately this problem mostly happen when you move solution or project in TFS from one location to another one. To fix this you could go to all referenced assemblies and change reference.
This would typically take very long time by 30-50 assemblies which you have in average.

So, right mouse click on project and unload it:
image

Then edit the project in editor:

image

Following shows (yellow marked) the assembly which is not correctly referenced. This assembly was originally on location MyProjects\packages. Then the project was moved to different location.

<ItemGroup>

    <Reference Include="Daenet.SecurityManager.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=173a861425037ca2, processorArchitecture=MSIL">

      <SpecificVersion>False</SpecificVersion>

      <HintPath>..\..\Assemblies\Daenet.SecurityManager.Client\Daenet.SecurityManager.Client.dll</HintPath>

    </Reference>

    <Reference Include="Daenet.System, Version=1.0.0.1, Culture=neutral, PublicKeyToken=ede0cf8eefc9ca50, processorArchitecture=MSIL">

      <SpecificVersion>False</SpecificVersion>

      <HintPath>..\..\Assemblies\Daenet.System\Daenet.System.dll</HintPath>

    </Reference>

    <Reference Include="Microsoft.CSharp" />

    <Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

      <Private>True</Private>      <HintPath>..\..\MyProject\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>

    </Reference>

    <Reference Include="System.Data.DataSetExtensions" />

    <Reference Include="System.Net.Http" />

    <Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

      <SpecificVersion>False</SpecificVersion>

      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.0\lib\net45\System.Net.Http.Formatting.dll</HintPath>

    </Reference>

 

The right path would be this one in my case.

      <Private>True</Private>      <HintPath>..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>

To me this was the best one to see all invalid references at once.
Unfortunately the VS fallback mechanism will not notify us if something is wrong and it will reference the default version, which will be a cause for very bad failures


Posted Aug 26 2014, 07:28 AM by Damir Dobric
developers.de is a .Net Community Blog powered by daenet GmbH.