ExecutionEngineException in ASP.NET MVC when mixing .NET Framework and .NET Standard assemblies

TL;DR: If you mix .NET Standard assemblies that depend on the System.Net.Http NuGet package into your .NET Framework ASP.NET MVC app, you are likely to encounter runtime crashes when your AppDomain unloads and reloads. The solution involves a binding redirect and a project build time setting.

This one was fun to figure out. I’m working on a project, where I really, really wanted to use Microsoft’s SpaServices package to enable server-side rendering for a Node frontend app. Fortunately, it only takes a little bit of glue to make them stick to an ASP.NET MVC 5 app, and you’re off to the races.

Unfortunately, it also comes with a nasty side effect of periodically crashing your app during development.

It took me a while to recognize the pattern, but after a dozen or so crashes, I finally figured out, that the exception always occurred after I had either edited the Web.config file or rebuilt the binaries — that is, whenever the AppDomain was unloaded and the app restarted.

The problem was initially triggered by ASP.NET Web Api’s EnsureInitialized call, but the culprit at the top of the stack was actually RuntimeAssembly.GetTypes() — so when I managed to trick Web Api into not triggering the problem, it was pushed forward to something Glimpse did. When I removed Glimpse, it moved to something that the ASP.NET MVC infrastructure did, and so on.

The actual problem is a combination of different issues: when running on the desktop framework, the System.Net.Http version you’re supposed to use is the one shipped in the framework. However, that version has some weird versioning quirks due to the fact that it isn’t just a .NET assembly, it’s also a Windows component. This leads to it having a version number that is smaller than the NuGet counterpart, which, in some edge cases, leads to the wrong assembly ending up in your process. I’m not sure where the memory corruption comes into play (and I’m not sure I want to know 😛), but fortunately the fix is simple.

You need to add a binding redirect for System.Net.Http and set ImplicitlyExpandNETStandardFacades to false in your project, as described in this GitHub comment.

Ah, System.Net.Http. Since it began shipping out-of-band, it’s just the gift that keeps on giving

I’m not bringing much new information to the table, but I hope this post at least helps someone else find the solution to the same issue without spending hours diagnosing it.

6 comments

  • Thank you, you solved a months long problem for me. I always suspected it was System.Net.Http.

  • Glad to hear this post was useful to someone! 🙂

  • This kind of thing is exactly the reason why I stopped working in .NET ages ago…

    • I can understand the sentiment, but I sort of suspect that most platforms have things like this. Granted, .NET Core did bring more of this about, particularly at the intersection of Core and non-Core.

  • Lauri, do you happen to have a sample solution that recreates this problem? We’re running into a similar issue but are having trouble isolating it in our large ASP.NET application. In our case, it is almost certainly related to a PuppeteerSharp nuget package that relies on .NET Standard System.Net.Http.

    I’ve created a sample application stripped down to the bones, but can’t find the key to recreating the issue.

    • Unfortunately, I don’t — the case was also a large legacy ASP.NET application, and having guessed the culprit and applied the fix, I didn’t feel the need for a smaller repro.

      For me, the trigger was the combination of an attached debugger together with editing Web.config.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.