Saturday, 8 November 2008

Working on ASP.NET MVC Beta and Preview code side-by-side

I have an app built against ASP.NET MVC Preview 3 that needs some tweaking, and I'm also working on a couple of projects using ASP.NET MVC Beta, so I'm in the slightly odd situation of trying to build and run preview 3 and beta projects side-by-side. (Yes, I will be updating this code to run against the beta version. I don't have time to do that this weekend, though, and I need some changes live before Monday afternoon.)

I've just checked-out the preview 3 project to make some changes, and although it builds absolutely fine, I'm seeing the lovely Yellow Screen of Death when I try and run it:

Server Error in '/' Application.

Method not found: 'Void System.Web.Mvc.RouteCollectionExtensions.IgnoreRoute   (System.Web.Routing.RouteCollection, System.String)'.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.  Exception Details: System.MissingMethodException: Method not found: 'Void System.Web.Mvc.RouteCollectionExtensions.IgnoreRoute(System.Web.Routing.RouteCollection, System.String)'. 

This is weird, because this code is deployed and running live on a box that doesn't have any versions of MVC installed; in theory, the project is entirely self-contained and XCOPY-deployable. First thing I tried was to shut down Visual Studio, uninstall ASP.NET MVC Beta, reinstall Preview 3, reload VS2008. That worked, so it's definitely the beta doing something strange. This project has hard-wired references to copies of the MVC assemblies in the \Dependencies folder of the solution, which are copied to the \bin folder during the build. It looks like the beta is installing something that's interfering with this process. Frustratingly, the installers also set up the MVC Web Application project type in Visual Studio, so although I can run the site without any versions of MVC installed, I can't open it in VS2008 because of the "project type is not supported" error.

Ok, first thing to realize is that, according to ScottGu's beta release blog post, the beta installs System.Web.Mvc, System.Web.Routing and System.Web.Abstractions to the GAC to allow them to be automatically updated. The preview versions of MVC would only install them to C:\Program Files\Microsoft ASP.NET\.

Given this particular chunk of web.config code:

<system.web>
 <compilation debug="true">
<assemblies>
    <add assembly="System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
   </assemblies>
</compilation>
</system.web>

the runtime is going to use the first version of System.Web.Mvc matching the specified culture, version number and public key token. This is significant because the CLR checks the GAC first when resolving assembly references - and if it finds a matching assembly in the GAC, it won't look anywhere else. The ASP.NET MVC previews and beta release all use the same assembly version, culture and public keys, so the CLR has no way of distinguishing between the preview 3 version of System.Web.Mvc and the beta version of the same assembly. They're different DLLs with different file versions, but because the assembly version is the same, the CLR regards them as the same assembly.

There are techniques you can use to override this behaviour, but, according to this thread on StackOverflow, these techniques only work if the assembly in the GAC has a different version to the assembly that's deployed with your application.

Ok - no problem, we'll just remove System.Web.Mvc from the GAC, by running gacutil.exe /u to uninstall it.

C:\Documents and Settings\dylan.beattie>gacutil /u system.web.mvc
Microsoft (R) .NET Global Assembly Cache Utility. Version 3.5.30729.1
Copyright (c) Microsoft Corporation. All rights reserved.

Assembly: system.web.mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL
Unable to uninstall: assembly is required by one or more applications
Pending references:
SCHEME: <windows_installer> ID: <msi> DESCRIPTION : <windows installer>
Number of assemblies uninstalled = 0
Number of failures = 0

C:\Documents and Settings\dylan.beattie>

Works on MY Machine! OK, that didn't work. Because we installed the ASP.NET MVC beta using Windows Installer, it's registered a dependency on System.Web.Mvc that means we can't uninstall it. So... registry hack time. This is the bit that might kill your PC, wife, cat, whatever.  Editing the registry is dangerous and can cause all kinds of problems, so read this stuff first, and if it sounds like a good idea, proceed at your own risk.

Fire up regedit and navigate to HKEY_CLASSES_ROOT\Installer\Assemblies\Global, and you should find a key in there called

System.Web.Mvc,version="1.0.0.0",culture="neutral",publicKeyToken="31BF3856AD364E35",processorArchitecture="MSIL"

I deleted this key. I also got a bit carried away and deleted the key

System.Web.Mvc,1.0.0.0,,31bf3856ad364e35,MSIL  from

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Fusion\GACChangeNotification\Default

as well... but I forgot to try gacutil /u first, so I don't know whether this second step is necessary or not. It seemed like a good idea, though, and doesn't appear to have broken anything, so you may or may not need to delete this second key as well.

Having removed those keys, I could run gacutil /u and remove System.Web.Mvc quite happily:

C:\>gacutil /u System.Web.Mvc
Microsoft (R) .NET Global Assembly Cache Utility. Version 3.5.30729.1
Copyright (c) Microsoft Corporation. All rights reserved.

Assembly: System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL
Uninstalled: System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL
Number of assemblies uninstalled = 1
Number of failures = 0

C:\> 

My preview 3 project now builds and runs quite happily against the System.Web.Mvc DLLs installed as part of the website, and the VS2008 MVC Project template still works just like it did before.

7 comments:

Matt said...

Awesome - thanks!
Btw, I didn't need to remove the second key, but not sure if any problems yet by not removing it.

Michael Paladino said...

Thanks. This solved an issue with which I've been struggling off and on for a couple of days now.

stucampbell said...

You're a life saver Dylan! :)

Carl said...

Thanks Dylan!

panjkov said...

gacutil /u with /force switch doesn't work either?

Nik said...

Thanks Dylan - helped loads.

rduht said...

We are sell wow gold and wow power leveling wow gold