Migrating MVC 4 app from .NET 4 to .NET 4.5 in Visual Studio 2012
Rumor has it that Windows Azure is going to support the .NET 4.5 runtime in the next couple of days (currently it's only available for websites): http://weblogs.asp.net/scottgu/archive/2012/10/25/net-4-5-now-supported-with-windows-azure-web-sites.aspx
As such, it seems worthwhile to write a crash-course for successfully migrating your .NET 4.0 app to .NET 4.5 (in Visual Studio 2012).
Before we get too far ahead, you may ask yourself "why upgrade at all." I'd argue that the persistent enum support and further hardening / performance improvements in EF 5.0 are about all that has to happen to make things worthwhile.
Microsoft provided the barest of bare-bones documentation about how to migrate an app to the latest framework (http://msdn.microsoft.com/en-us/library/ff657133.aspx), and since it took me a weekend of tinkering to get things working, I figured someone else may benefit from the head scratching (banging) I went through to get things up and running.
The Windows Azure emulator doesn't currently let you develop locally with .NET 4.5 (haven't figured out how to get this working yet), but you can still debug and get your app running locally without the the Azure emulator. That is what this guide should help provide.
Without further adieu...
Step 1 - Update your Target Framework
To update your target framework, open Visual Studio (but do NOT open your project). We need to edit the Target Framework attribute in *.csproj files. Visual Studio locks those files down while in use, so it's moot to try and edit while your project is open.
Click the Edit toolbar -> Find and Replace -> Find in Files and search for targetFramework for any file matching *.csproj file.
You will see a number of files appear and you'll want to click into every single TargetFramework xml tag's value from v4.0 to v4.5
Step 2 - Re-Install your NuGet packages
This is a bit more painful, but you'll survive. I manually uninstalled and re-installed every NuGet package starting with my Unit Test projects on down to my MVC app and model projects within my solution. I made a backup of my packages.config file for reference (located in solution_root_folder/project_folder/packages.config). This IS painful, but keeping a backup of the packages.config file for reference and doing some web searches to figure out what package goes where will be the way to go.
After uninstalling all your packages, go ahead and re-install one by one starting with your lowest level (e.g. closest code to the database) first. It's not fun, but this is the safest way to make sure you get all of your dependencies back up and running. When you get back to the point of a clean build working successfully, breath a sigh of relief, take a walk outside, etc. If you don't have MVC's membership in play (or are using home-rolled/custom membership providers), you should be able to deploy your MVC 4 app without issue. But if you are using ASP.NET SImpleMembership or aspnet_Membership (circa .NET 2.0), read on...
Step 3 - Fix your membership settings / connection strings
When I re-insalled all my NuGet packages, I had a successful deploy until I logged into my app, at which point I got weird errors. I like to name my connection strings after my app name. By doing this and not overriding the LocalSQLServer connection string (which was previously never mentioned in code / web.config files anywhere in my solution), much pain was endured.
First and foremost, add a </clear> tag to the start of your <connectionStrings> tag in your web.config file. Next, add a new connection string (a duplicate of your existing one) and call is "LocalSQLServer". My connectionStrings element now has three children:
- </clear>
- <add name="LocalSQLServer" ...
- <add name="MyGreatAppConnectionStringName" ...
A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified)
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.
SQLExpress database file auto-creation error:
The connection string specifies a local Sql Server Express instance using a database location within the application's App_Data directory. The provider attempted to automatically create the application services database because the provider determined that the database does not exist. The following configuration requirements are necessary to successfully check for existence of the application services database and automatically create the application services database:
If the application is running on either Windows 7 or Windows Server 2008R2, special configuration steps are necessary to enable automatic creation of the provider database. Additional information is available at: http://go.microsoft.com/fwlink/?LinkId=160102. If the application's App_Data directory does not already exist, the web server account must have read and write access to the application's directory. This is necessary because the web server account will automatically create the App_Data directory if it does not already exist.
If the application's App_Data directory already exists, the web server account only requires read and write access to the application's App_Data directory. This is necessary because the web server account will attempt to verify that the Sql Server Express database already exists within the application's App_Data directory. Revoking read access on the App_Data directory from the web server account will prevent the provider from correctly determining if the Sql Server Express database already exists. This will cause an error when the provider attempts to create a duplicate of an already existing database. Write access is required because the web server account's credentials are used when creating the new database.
Sql Server Express must be installed on the machine.
The process identity for the web server account must have a local user profile. See the readme document for details on how to create a local user profile for both machine and domain accounts.
You're probably thinking you're out of the woods now, right? Sadly, I ran into my next series of errors thinking along the same lines.
Step 4 - More NuGet Package Installations!!!
After fixing up my web.config file, I had an error popping up that looked eerily like the previous version of ASP.NET Membership, but since I was using the latest and greatest membership providers, this had me a bit confused. The error I was receiving is below:
Could not find stored procedure 'dbo.aspnet_CheckSchemaVersion'. 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.Data.SqlClient.SqlException: Could not find stored procedure 'dbo.aspnet_CheckSchemaVersion'.
I had to install to my MVC 4 project another NuGet package:
Install-Package System.Web.Providers
This duplicated a number of lines in web.config file and I had to remove the original and use the newly-added provider tags replacing the connectionStringName attribute with my connect strings name. The providers I had duplicated entries for after installing the System.Web.Providers package were:
- DefaultProfileProvider
- DefaultMembershipProvider
- DefaultRoleProvider
Okie dokie, that should get you out of the woods and back to coding. Yes, it was painful, but hopefully this helps someone else out on the interwebs figure out all the configurations necessary to upgrade an app to the latest .NET 4.5 framework!