Scott Hanselman

Integrating ASP.NET MVC 3 into existing upgraded ASP.NET 4 Web Forms applications

January 06, 2011 Comment on this post [42] Posted in ASP.NET | ASP.NET MVC | VS2010
Sponsored By

I got an interesting question recently from a gentleman who has an existing ASP.NET WebForms 2.0 application that works just fine. He's upgraded it to ASP.NET 4 and it still works great, but now he wants to add some ASP.NET MVC pages to it. He doesn't want to rewrite the application.

A few years ago I did a post on "Hybrid" ASP.NET applications. The goal was to reinforce the point that you can have ASP.NET applications that are both WebForms and MVC (as well as WCF and ASMX Web Services and on and on.) While the File|New Project dialog gives you a choice between This and That, in fact it's all ASP.NET underneath. You are welcome to mix and match "cafeteria style" and create apps in any combination you'd like.

The easiest way to add ASP.NET MVC 3 to an upgraded ASP.NET 2.0 WebForms application:

  • Run the Upgrade Wizard (open the  Visual Studio2008 Web Application in Visual Studio 2010)
  • Create a default ASP.NET MVC application for reference (you'll throw it away later)
  • Use a differencing tool like Beyond Compare to integrate the new web.config entries from the ASP.NET MVC sections into the upgraded ASP.NET WebForms application
  • Dance

Here's the longer more detailed version of the above.

Upgrading an ASP.NET 2.0 WebForms Application

I've created a simple Visual Studio 2008 ASP.NET WebForms Application running under .NET 2. It's a simple calculator.

WebApplication1 - Microsoft Visual Studio (7)

It works nicely. Now, open this application in Visual Studio 2010. You'll get the Conversion/Upgrade Wizard.

Visual Studio Conversion Wizard (6)

Next, Next, Yada, Yada, Yada, Finish. You'll get an prompt to upgrade the 2.0 application to .NET Framework 4. Click Yes.

Web Site targeting older .Net Framework Found (8)

Here's the same WebForms application, now upgraded in Visual Studio 2010. It still runs and it's still WebForms. Or, more accurately, it continues to  be ASP.NET.

WebApplication1 - Microsoft Visual Studio (9) 

I'm going to take a new default ASP.NET MVC 3 application and Beyond Compare and compare the upgraded app with the default app.

WebApplication1 _--_ MvcApplication1 - Folder Compare - Beyond Compare (10)

I'll copy over these folders and files:

  • Content
  • Controllers
  • Models
  • Scripts
  • Views
  • Global.asax, Global.asax.cs

Now, here's the before and after references from the upgraded application. The old on the left and the new on the right.

New ReferencesReferences

Here's the references I added.

  • Microsoft.CSharp
    • (as this was a C# app)
  • System.Web.Mvc
    • From \Program Files (x86)\Microsoft ASP.NET\ASP.NET MVC 3\Assemblies
  • System.Web.WebPages and System.Web.Razor
    • From \Program Files (x86)\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies
  • System.ComponentModel.DataAnnotations

Next, add these sections to the Web.config. Again, it's easier to use a diff tool and you might have a little trial and error.

Thought: This might be a nice NuGet package for someone to make...

Add these settings in appSettings:

<appSettings>
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
</appSettings>

Add these assembly elements under compilation:

<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</assemblies>
</compilation>

Add these namespaces in pages:

<system.web>
<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.Routing" />
<add namespace="System.Web.WebPages"/>
</namespaces>
</pages>
</system.web>

If you're running IIS7 at some point, which I'm sure you will, add these:

<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>

And finally add this assembly binding redirect, just in case you've got ASP.NET MVC 1 or 2 assemblies in your Global Assembly Cache (GAC).

<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

Also, make sure you merge in the Global.asax.cs so that your Routes are registered at application startup.

public class SomeHybrid: System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}

public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);

}

protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();

RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}

Now, at this point I can visit both pages. The WebForms page is a file on disk, so ASP.NET routing passes requests directly on to this page when I /default.aspx. The ASP.NET Routing engine is engaged so I can also hit /Home/Index.

If I want to get fancy, I can add a PageRoute so I have pretty URLs when visit my WebForms pages as well. Just add a route in the Global.asax like this. Make sure that simple routes like these come first, as the default ASP.NET MVC route is very "greedy" and would gobble up a simple URL like /calculator

routes.MapPageRoute("WebFormThing", "Calculator", "~/Default.aspx");

Now I can visit /Calculator and the request is routed to /Default.aspx. And of course, my ASP.NET MVC 3 Razor pages like /Home/Index work also.

http___localhost_12089_Calculator - Windows Internet Explorer (18)

Finally, just to make the point, here's the Default.aspx from the WebForms part of my new app next to the source for a Razor page.

WebApplication1 - Microsoft Visual Studio (16)

You CAN have it all, Dear Reader. Enjoy.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service
January 06, 2011 13:04
Pah! I laugh at your "Hybrid". Our web app is a hybrid ASP WebForms, ASP MVC and ASP Classic site :-)
January 06, 2011 15:03
Thank you! Great article Scott!
January 06, 2011 16:57
The problem 90% of devs will encounter is 'how do we handle master pages'

Can you comment/ add recommendations ?
January 06, 2011 18:09
Steve said it ... as far as I know, there is no way to mix traditional ASP.NET, MVC, and MVC/Razor master pages. This leads to having to maintain three versions of essentially the same thing.
January 06, 2011 18:44
I haven't been able of performing step 4 =(
January 06, 2011 19:04
Wow - good timing. I just upgraded my project to .NET 4 yesterday! Today, the MVC fun begins...
January 06, 2011 19:52
Thank you Scott. For many apps, this is the most practical way to embrace MVC.
January 06, 2011 20:12
Great article! Thanks Scott!
January 06, 2011 22:58
I second Steve's sentiments. I tried to go hybrid and the master pages just totally threw me off course. Supporting multiple copies of the same thing is soul sucking. I recommend completely avoiding this route.
January 07, 2011 4:04
You neglected to deal with the fact that MVC takes over the / route so you'd have to go to www.domain.com/default.aspx to get that otherwise you get /home/index by default. I tend to keep old school master pages and only use MVC for the programmatic stuff, like ashx handlers for instance.
January 07, 2011 4:30
Whatever happened to VS providing a dialog with checkboxes allowing us to select the "features" a project will have? A MVC checkbox, a webforms checkbox, etc...
January 07, 2011 4:53
Hitman - I'm working on it. ;)

William - Yes, but you can take over that route, no?

Robert - I'll blog a solution that lets you mix and match master pages soon.
January 07, 2011 5:20
Hi Scott,

If I am running this hybird app in Azure, would I need the 2 lines of <system.webServer> settings that you have here for IIS7?

Thanks,
Ray.
Ray
January 07, 2011 5:28
Ray - I have no idea! ;) I'm not into Azure. Let me know?
January 07, 2011 8:47
It Seems that you are missing views web.config.
January 07, 2011 15:28
I can't get this to work. The bit I'm struggling with is: 'Also, make sure you merge in the Global.asax.cs so that your Routes are registered at application startup.'

I'm getting an issue with loading the copied over Global.asax file. The MVC app was called MV3Application and this is still in the asax file. The error is then:

Source Error:

Line 1: <%@ Application Codebehind="Global.asax.cs" Inherits="MVC3Application.MvcApplication" Language="C#" %>

I'm a newbie .NET developer. Have I missed a step?
January 07, 2011 19:03
very through article. thanks a lot !
January 07, 2011 23:05
Matt - Did you copy the .cs file also? What's the name of the other app?
January 08, 2011 0:05
Hi All Of You!,
I am a very, very, newbie to all kind about how to program in any way what ever. So what more about I have to say only nothing else to explain like this. Before I have to say to you sorry about my bad spelling english because my origin language is German or Dutch. My question to you are now reading this is:

If anyone knows a way to teach a newbie like me the knowledge I would like to have please give me a hug and do give me good information where to learn what I have to know about the needs for what my project is.

More about my project: You will find at my homepage.

Thank you for your time and participation to read this newbie question.
And thank you for review my project at my homepage I am very waiting for your feedback.
My homepage is in the language English, Dutch and German.

P.S.
Aditional information about project:
My idea is to merge existing systems in the daily money market with a new vision how to participate in the daily average of costs about consumer spendings for all kind of products. The target is to start this system with low amount charges to reinvest in this daily consumer spendings. The profit is a win, win, situation for companies and consumers who participate in this system,

©The system is based on the back office network for POS machines who uses this back office network system.®

My Published Email:viewunity@india.org in this session is only a autorespond account and if you mail me you will get more information about my project.

To the Admin of this session: I would be not wondering if you delete this message but I would like to ask you if you do please forward this information to anyone who could bring me more along the way I will like to go.
The first question at the time Microsoft Windows was launched was ''Where Do You Go Today''
Sometimes I think people forget this quest.
Kind Regard Viewunity Bonnen.
January 08, 2011 0:29
Hi Scott, I searched around and it seems ok to have those in Azure. BTW, do you have any posts/discussions of your take of Win Azure, why you are not into it and so on, I'm sure we'd all like to know your perspective on it? Thanks -Ray.
Ray
January 08, 2011 8:02
I've been waiting for this hybrid idea to come out I'd like to use the best of both worlds can't wait for the MasterPage artical another thing I'm falling over backwards about is code first data access that flows from your finger tips looking forward to more articales about that allso thanks for the great stuff you put out good talk at pdc this year allso

thanks Scott

@Viewunity Bonen www.asp.net
January 08, 2011 10:05
Instead of merging the application, Can we have a separate folder for MVC in the asp.net web application?
January 09, 2011 18:09
nice post. very helpful...
January 10, 2011 5:56
hey scott - any idea how possible it would be to integrate MVC into SharePoint?
January 13, 2011 13:11
I think the MVC is not component oriented as mush as WebForms are. So the ASP.NET WebForms will not be replaced completely by MVC. I know WebForms are to old and should be replaced by another technology, but as I say I think that is not MVC.

Am I correct? Or the WebForms will be replaced by MVC at all?
January 24, 2011 7:47
Hi Scott,
Waiting for the Master page solution (solution that lets you mix and match master pages) !!!!!!!!!!.

Cheers
January 24, 2011 15:14
Suminda - I'll try to write that today!
January 25, 2011 16:28
This screeaaams NuGet
June 01, 2011 16:21
Hi Scott,

did you ever get around to that blog on mixed master pages? and just to throw another ball in the air how about with Spring.Net in the mix and it's master page implementation! :0)

Cheers,
Griff
June 01, 2011 17:24
Great article.
I have an existing ASP.NET application in VB.Net and could add ASP.NET MVC pages to it.
Is it possible to add ASP.NET MVC parts written in C# to this existing VB.net application?
Many thanks
June 09, 2011 22:05
Hi Scott,

I wonder why choose this approach rather than at least two web projects which share session?

I've trying to decide between the approach you listed here, or a solutions with two web projects that share session state (and then shared code projects for common classes or services between the two). I'm guessing there would be some cost associated with the two separate web projects such as some more IIS configuration using two web apps and possibly more duplicated code. But other than that I'm leaning towards the 2 project approach since I believe the hybrid would be more difficult to maintain after transitioning all pages and controls to MVC --- because it would be an effort to detangle.

What do you think?

Thank,
John
June 16, 2011 23:15
John C - I'm not a session state fan, but my answer is that you'd have less duplication in one logical app if you just kept it all in one physical application. I don't agree that it would be a huge effort to detangle. Also, this assume that there's already some organization in your app (DB and Business Layers in other projects, etc.)
June 20, 2011 20:23
Thanks for the reply Scott. I started coming to similar conclusions as well.
-John
July 12, 2011 16:00
I tried this myself at the weekend, and came across enough issues to put me off and switch to the greenfield approach of a rewrite..

- no mvc context items (such as 'add view' when you right click a controller action)
- mvc scaffolding does not work with it (it complains about the project type not being mvc)
- if you rely on 3rd party controls (such as telerik radupload for example) you might find they break once you introduce mvc
-no razor intellisense

maybe there are workarounds, but i started to get nervous about investing too much time into something that might bite me further down the line.
July 14, 2011 9:13
Guy - If you are seeing no tooling (which is what you're describing) then just add the MVC Project Guid to the list of Project Guids in the .csproj. That's all and it will fix all the other issues.
July 14, 2011 12:05
Ah, ok, i did wonder whether there was a flag that would trigger the vis studio items, but figured this may break the webforms stuff.

Thanks for the info Scott.
September 07, 2011 2:38
I have a bit of quandry-

porting an app from aspx to mvc

have a set of deep directories which have both content files (images) and html, served via default.aspx in each folder.

I want to keep the images in their original paths, so i copied over the whole dir. But I can't find a way to route things so that content is served up at the same url as the default.aspx woudl have been, ie site.com/path/ ... since this path exists, the route never fires.

any ideas....?
September 07, 2011 2:55
btw- i wouldnt mind even leaving a default.aspx file in each folder, and just have it fire off a route or something similar... if there's a way to do this.
September 07, 2011 3:55
I found the IgnoreRoute for axd files only did the root path which wasn't enough for my site and I would guess lots of other sites.

In the end I went with this:

routes.Ignore("{*allaxd}", new { allaxd = @".*\.axd(/.*)?" });

This allowed the Microsoft Charting controls to function requesting axd files at any path on the site.

Scott, I think this would be pretty common and could be worth updating your code in the post to handle this.
September 07, 2011 20:45

Hi Scott,

As per your article I follow the steps to integrate WebApp with MVC application. I am successfully integrated MVC project into WebApp(C#).

The problem is If I choose WebApp as VB.NET project, and integrated with MVC project. In this case the request is not routing to corresponding MVC files.

What could be the reason not routing to MVC. Do we need to plug some extra dlls?

Thanks
Gopal

September 30, 2011 19:05
Hi,

I upgraded my aspx webforms web application from 3.5 to 4.0 and did the changes to support MVC. I did the above mentioned steps. But the thing is when i try to add new item, I dont get MVC3 Razor page in add new item dialog. I have installed MVC3. Also I am not able to add reference to System.Web.Razor as the dll is not coming up in .Net references.

Kindly give me your suggestions.

Am i missing on something?

Thanks and Regards,
Gangadharan
September 30, 2011 21:36
Gangadharan - You'll need to add the MVC3 project guid manually to the CSProj if it didn't get added automatically.

Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.