One of my customers contacted me a couple of weeks ago with this issue, but had a different setup that ruled out all the other resolutions he’d come across online. First, the error:
Nothing really helpful in there, or in a Failed Request Trace (I’d love to see some decent ASP.NET events someday). He’d already started looking at some of the more common causes reported online, like:
- Missing the ‘webpages:Enabled’ setting in the app’s web.config
- Incorrect app pool settings
- ASP.NET MVC not being GAC’d on the server
- Handler config issues
But as mentioned earlier, their setup ruled out all of those. They have 3 web servers in the farm, and all 3 are set up to use IIS’s Shared Configuration feature, which ruled out number 2, and partially number 4 (though the handlers could have been overridden in the app’s web.config). Additionally, the site uses shared content as well, meaning the site is pointing to a UNC share for the web content. This meant all 3 nodes were using the same app-level web.config, which ruled out number 1 and 4. That left number 3, which was ruled out by the fact that the app developers had BIN-deployed the necessary Razor assemblies. While we were troubleshooting, I did have him check to be sure that someone else hadn’t installed MVC on the working web servers, but no, MVC wasn’t installed on any of them. Running out of ideas, we did check out the root web.config and the machine.config on the bad server (Comparing against a working server), but the good and bad copies were identical. We were both stuck at that point, but I decided to have him generate Process Monitor logs of both a working and failing scenario to see if anything happened to pop up there. Sure enough, I got lucky.
While reviewing those logs side by side (multimon FTW!), I noticed one glaring difference in the activity inside the hosting w3wp when he requested default.cshtml. In the working instance, we got to the point of reading the preStartInitList.web file for the app, and subsequently attempted to load the necessary Razor assemblies. The process did fail to load them from the GAC and framework directories as expected (since MVC isn’t installed locally), but was able to pull them from the BIN directory on the remote content share:
In the failing instance, no attempt to load the Razor assemblies ever happened after reading preStartInitList.web:
When he checked preStartInitList.web on both servers, the copy on the working server listed the following assemblies to be loaded when the app started:
System.Web.WebPages.Razor, Version=220.127.116.11, Culture=neutral, PublicKeyToken=31bf3856ad364e35
System.Web.WebPages.Deployment, Version=18.104.22.168, Culture=neutral, PublicKeyToken=31bf3856ad364e35
System.Web.WebPages, Version=22.214.171.124, Culture=neutral, PublicKeyToken=31bf3856ad364e35
While the copy on the failing server was blank. He deleted the copy on the failing server, restarted the app pool, and things started working as expected once BuildManager regenerated the preStartInitList.web with the correct entries.
Just another thing to look for if you’re seeing this error pop up