Sometimes things just blow up.
If you have recently attempted to create a new ASP.NET MVC5 project (or any new Web Project within Visual Studio 2013) and decided that you wanted some of that sweet SignalR magic in your application, then you may have encountered the following error :
An exception of type ‘System.IO.FileLoadException’ occurred in Microsoft.AspNet.SignalR.Core.dll but was not handled in user code.
Additional information: Could not load file or assembly ‘Microsoft.Owin, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35′ or one of its dependencies. The located assembly’s manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
This can easily be reproduced through the following steps :
- Create a new Web Application Project in Visual Studio 2013 that uses built-in Forms Authentication (Individual User Accounts).
- Add the SignalR package through NuGet.
- Attempt to add the following code to your
Startup.cs
file :
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
// Add SignalR Mappings
app.MapSignalR();
ConfigureAuth(app);
}
}
If you did everything right, then grab some popcorn because you are about to see this :
Why is this happening to me?
Of all of the things to blame, we are going to choose NuGet for this one.
This is currently a known issue within NuGet. The reason for this is that SignalR and some other binaries are built with a dependency over Microsoft.Owin Version 2.0.0, however the appropriate assembly binding redirects are not occurring. This causes a problem as the latest available version of Microsoft.Owin in the public NuGet feed is greater than 2.0.0.
Okay. But how do I fix it?
There are two options here, which I have each had success with so I’ll start with the easiest approach, installing a specific updated version of Microsoft.Owin
and Microsoft.Owin.Security
and ensuring that you are properly targeting it within your web.config.
You can do this within the following steps :
- Access the NuGet command-line tool within Visual Studio, accessible under Tools > Library Package Manager > Package Manager Console.
- Install an updated version of Microsoft.Owin and Microsoft.Owin.Security (2.0.1, 2.1.0, 2.2.0 or any other version) using the following command :
Install-Package Microsoft.Owin -Version 2.1.0
Install-Package Microsoft.Owin.Security -Version 2.1.0
- Ensure that your web.config has the appropriate
attributes to target the version you selected as seen below :
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- Other Assemblies here -->
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<!-- Notice this targets 2.1.0.0 -->
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<!-- Notice this targets 2.1.0.0 -->
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
The other longer and seemingly less reliable approach
This method appears to only work if the version of Owin that was installed through NuGet is already greater than one of the dependencies that you already have.
The second option involves creating a Console application and then add the SignalR package to it. Then copy the bindingRedirects
from the app.config file of this application to the web.config file in your previous exception-infested MVC application (as Console applications don’t have this same issue).
You really just need to update the oldVersion
and newVersion
attributes within the <bindingRedirect>
sections for your Microsoft.Owin
and Microsoft.Owin.Security
assemblies within the assemblyBinding>
section of your web.config from :
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- Other <assemblyBinding> elements for your Project -->
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
to :
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- Other <assemblyBinding> elements for your Project -->
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.2.0" newVersion="2.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.2.0" newVersion="2.0.2.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
Or more simply, change the <bindingRedirect>
sections for each of your Owin-related assemblies from :
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
to :
<bindingRedirect oldVersion="0.0.0.0-2.0.2.0" newVersion="2.0.2.0" />