Assembly Version Mismatch and Bulk Package Update

In our solution we have 6 projects just for tests. Every test project has Autofixture, Moq and Autofixture with Automocking using Moq installed. The problem is Autofixture compiled against on Moq version 3. But Moq version 4 has been released long time ago.

So every time new Moq version comes out, I need to update Moq packages in all testing projects. You can do that through Nuget GUI in one go, but after that you need to update Assembly binding redirect.

Binding redirect allows your projects to have library A version 1.0 that depends on library B version 2.0. But actually your installation includes library B of version 3.0. Without binding redirect you would get a nasty runtime exception like this:

System.IO.FileLoadException : Could not load file or assembly 'Moq, Version=3.1.416.3, Culture=neutral, PublicKeyToken=69f491c39445e920' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

That basically means library A tried to load library B with version 2, as it was compiled against version 2. You might spend a lot of time trying to chase your tail, because the actual library B will be there. Only the version will be different.

To resolve this, you can add a binding redirect in your web.config or app.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Moq" publicKeyToken="69f491c39445e920" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.1.1308.2321" newVersion="4.1.1308.2321" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration> 

This will tell runtime to load assembly B with version 3.0 instead of old version.

So back to my problem. Before today, every time I updated Moq, I had to go into every Test project and manually update binding redirect with a new version. Today I was mocking (pun intended) about with nuget packages and nuget command line. And I read through this page: Package Manager Console Powershell Reference. First entry there talks about Add-BindingRedirect. Turns out I don’t have to manually add binding redirects. So in nuget console in VS I can just go:

> Add-BindingRedirect

And that would scan all referenced assemblies, find version mismatch and add required bindings. You also can specify project name – where to add the binding redirect. Also there is another command:

> Get-Project -All

This lists all projects in your solution.

Now, if you know a bit of PowerShell, you can pipe the commands one into another:

> Get-Project -All | Where-Object {$_.FullName -Match "Tests"} | Add-BindingRedirect

This will get all projects, filter them by name, find all projects that has name mathing “Tests” and add binding redirects in them. Crickey!

So my new workflow for updating Moq packages is

>Update-Package Moq

This updates Moq in all projects. Then I go

> Get-Project -All | Where-Object {$_.FullName -Match "Tests"} | Add-BindingRedirect

This updates all biding redirects for Moq to a new version.

Now, instead of 10 minutes for updating Moq package, I only need 30 seconds. PROFIT!

What other hacks do you know with Nuget console?

P.S. Here is a nice list of PowerShell commands you can use in Visual Studio