Reverting c# MVC projects from .NET 4.5 to 4.0

I don’t know if I’ve ever mentioned this, but my day job is programming. When I’ve said in the past that most of my day is filled with reading, I wasn’t kidding. A tiny percentage of developing software is writing new code. Most of it is reading manuals, understanding old code, and researching problems. At the end of the day, software developers are just highly specialized researchers.

With that in mind, google is our friend. I’m typing this on my writing blog in hopes this solution to a recent problem I’ve had will get a hit in other people’s search results. So down to tass bracks. Or something like that.

MSVS 2013 Community Edition – Reverting (or downgrading) and ASP.NET MVC project from .NET 4.5 to .NET 4.0

I assumed this would have been done plenty of times, but apparently there have been some changes. In the old days, reverting .NET versions meant changing a project setting and manually changing dependent DLLs.

That’s not the case anymore, at least not in community edition, because NUGET is completely integrated into the project. So much so that new projects and solutions no longer reference installed copies of DLLs by default. They grab them from NUGET instead. So that means dependencies are actually NUGET entries in the nuget package config and in the packages folder structure.

This is kinda cool for a lot of reasons, but it is frustrating for anyone having issues because fixing dependencies means going through NUGET. This is one of those situations. So here’s the steps that should get you back to a working state, at least for the standard dependencies that come with MVC.

Step 1. This is the obvious one. Go to all of the projects in your solution, right click them in the solution explorer, click properties, and change the Target Framework to .NET Framework 4 in the Application “tab.”

After this step be sure to clean the project, close visual studio, and reopen it. Save changes to the solution if necessary. All versions of MSVS like to hold onto old project settings in memory. So it’s good practice to restart VS on project level changes.

Step 2. Click Tools->NuGet Package Manager->Manage Nuget Packages for Solution. When this menu appears, click on the Update tab and click the Update All button. This should bring up an update menu and ask for approval to licenses once or twice. After this is done, clean and rebuild to see warnings about missing dependencies.

This is another good time to restart Visual Studio and save solution changes if necessary.

Step 3. Return to the Tools->NuGet Package Manager->Manage Nuget Packages for Solution and remove the System.Web.MVC project from the solution. This may cause an error for a dependent package. If it does, remove the dependent package and make sure that System.Web.MVC is uninstalled.

Now click the Online tab, select nuget.org and search for MVC 4. Find the Microsoft ASP.NET MVC 4 package and click install. This should bring in dependencies such as the Razor and Webpages packages.

Again, these are project level changes. Restart Visual Studio and save if there are any changes to be saved.

Step 4. Here comes the hard part. All of the references in code should be solved now. (If not, find repeat steps 2 and 3 to remove the incorrect version of the dependency and install a new one through the NuGet Package Manager).

The solution should build properly now and you should be able to debug it. However when you run the web app and visit a view, you should get a runtime error. All of these project fixes have updated the dependency files, the project references, the project versions, and the solution information. But none of the web.config files that sit in the areas folders will be updated.

Copy the portion of the error from the error message that displays the package name and version (i.e. System.Web.Mvc, Version=5.2.2.0). Now view the References for the web app project and select the matching dependency, and view its Properties. (I.e. System.Web.Mvc version 4.0.0.1). With the new version found, perform a Find in Files for the project on the string that you copied from the error, and replace the version number. There should be quite a few of these if you rely heavily on the Areas feature in MVC 4.

Repeat this step as many times as necessary until all web.configs are updated with the correct version numbers. Expect to do this at least for System.Web.WebPages.Razor and System.Web.MVC.

Now you should be good run the application locally.

Step 5. Now that the individual area/view web configs have been updated, the web.config for the web application needs to be reverted. This will not affect running the application locally (debug or release), but when you try to publish the website IIS7 will choke on the web.config that has artifacts left over from 4.5 and fail silently. For me, it was redirecting to the IIS7 Welcome Screen and rendering blank pages for any controller/action combination thrown at it.

The biggest issue was the webpages:Version pointing to the wrong .dll version. .NET 4.5 had pointed to 3.0.0.0 but the correct version for .NET 4.0 is 2.0.0.0. This can be confirmed by viewing the properties of the reference in the project.

This changed the section under <appSettings> from:

<add key=”webpages:Version” value=”3.0.0.0” />

to

<add key=”webpages:Version” value=”2.0.0.0” />

There were a couple changes <system.web>. First, remove the tag:

<httpRuntime />

Second, add namespaces for the resources.

<pages>
<namespaces>
<add namespace=”System.Web.Helpers” />
<add namespace=”System.Web.Mvc” />
<add namespace=”System.Web.Mvc.Ajax” />
<add namespace=”System.Web.Mvc.Html” />
<add namespace=”System.Web.Optimization” />
<add namespace=”System.Web.Routing” />
<add namespace=”System.Web.WebPages” />
</namespaces>
</pages>

Finally, the <system.webServer> section needed to be added inside the <configuration> tag:

<system.webServer>
<validation validateIntegratedModeConfiguration=”false” />
<modules runAllManagedModulesForAllRequests=”true” />
<handlers>
<remove name=”ExtensionlessUrlHandler-ISAPI-4.0_32bit” />
<remove name=”ExtensionlessUrlHandler-ISAPI-4.0_64bit” />
<remove name=”ExtensionlessUrlHandler-Integrated-4.0″ />
<add name=”ExtensionlessUrlHandler-ISAPI-4.0_32bit” path=”*.” verb=”GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS” modules=”IsapiModule” scriptProcessor=”%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll” preCondition=”classicMode,runtimeVersionv4.0,bitness32″ responseBufferLimit=”0″ />
<add name=”ExtensionlessUrlHandler-ISAPI-4.0_64bit” path=”*.” verb=”GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS” modules=”IsapiModule” scriptProcessor=”%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll” preCondition=”classicMode,runtimeVersionv4.0,bitness64″ responseBufferLimit=”0″ />
<add name=”ExtensionlessUrlHandler-Integrated-4.0″ path=”*.” verb=”GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS” type=”System.Web.Handlers.TransferRequestHandler” preCondition=”integratedMode,runtimeVersionv4.0″ />
</handlers>
</system.webServer>

Now you should be able to run the web app locally and also push to a server. Give it a try, and if you need further help I’d be happy to lend a hand out. Just leave a comment.

P.S. You will probably have Entity Framework errors to fix after this downgrade. If I run into that issue, I’ll post an update with the fix. From what I understand, there are additional dependencies to uninstall/reinstall as well as mappings to update.
We’ll return to our irregularly scheduled writing blog next week!

UPDATE!

Turns out the version of MVC showing on the DLL was not entirely correct. My version reported as 4.0.0.1 but the proper version for the web.config files is 4.0.0.0. I confirmed this with a dummy project started in MVC 4.0.This causes a symptom of HTML and URL helpers, as well as View models, being unrecognized in Razor; even though they worked fine at runtime.

So I ended up having to update all of my web.config files in my view folders again. In my case it went from:

<system.web.webPages.razor>
<host factoryType=”System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.1, Culture=neutral, PublicKeyToken=31BF3856AD364E35″ />…

to

<system.web.webPages.razor>
<host factoryType=”System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35″ />…

Voila! The helpers and model objects are recognized again. I also double checked that PublicKeyToken property as well and it seems to be the same between 4.5 and 4.0. Go figure. Just make sure you do this for the base View folder and the View folder in all of the Areas. You’ll probably have to clean and rebuild, but despite all my shouting earlier I didn’t have to restart Visual Studio again after making the fix. Small win for Microsoft!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s