In a recent project, the above exception was thrown when returning from a web service call. Interestingly, the exception was only thrown if the code was running within a web application. It would run fine when executed in an executable or even the Visual Studio development web server. At first I suspected some sort of permission problem but that couldn't really explain that particular error message. Next suspect was the shadow-copy feature of ASP.NET: The runtime does not actually run the assemblies from the path the IIS virtual directory points. Instead it copies all assemblies to the Temporary ASP.NET Files (C:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files on x86 machines or C:\Windows\Microsoft.NET\Framework64\v2.0.50727\Temporary ASP.NET Files on x64 machines) and executes them from there. So I added two lines of code right before the exception would be thrown:
Upon execution, the trace output was the following:
1: c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\c88143cc\98574940\assembly\dl3\98dad73b\f3cf1948_ddb4c801\MyAssembly.DLL
This was the problem: One assembly was loaded from two different sources. What was the cause? Turns out that the first assembly was loaded because of an assembly reference. This way it was correctly placed in the Temporary ASP.NET Files. But the second instance of the assembly was loaded via reflection with a call to System.Reflection.Assembly.LoadFile. The solution is to use System.Reflection.Assembly.LoadFrom instead of the LoadFile method.
Why is this a solution? The main difference between LoadFrom and LoadFile is that LoadFrom goes through the normal Fusion bind process, thus allowing assembly redirection to happen. LoadFile on the other hand, just loads the assembly from the specified location.
For more information on this, see this blog posting from Suzanne Cooks blog.