The ASP.NET MVC bug is quickly catching up with many developers because of the cool features of the framework like:

Convention over configuration

Don't repeat yourself (a.k.a. the DRY principle)

Pluggable architecture

The side effect of this is the framework supports Test Driven Development a.k.a. TDD. This article specifically talks about making ASP.NET MVC work with the current WebForms applications. This is not a tutorial for learning ASP.NET MVC. For learning ASP.NET MVC, refer to the "References" section.

Every solution should have a pertinent problem that every developer is trying to solve. Here are a few of the reasons why you might want to run both the project types together:

Web forms are very good at encapsulating view logic into components. You may be comfortable developing complex solutions using technology you already know.

The ASP.NET MVC pluggable architecture allows TDD. In some organizations, the code coverage policy may be very strict. And, what better way to fulfill this policy requirement better than writing tests?

You may be working with an existing complex ASP.NET application and may be in the migration phase. The migration needs to happen incrementally without impacting the existing functionality.

There is no code demonstration as the code is not central to the purpose of this article. The core of the article is the configuration activities which enables you to work with WebForms and MVC in harmony.

The ASP.NET MVC framework has a high degree of support for pluggability and extensibility. The crux of the ASP.NET MVC framework is the following three assemblies shown in the figure which extends the System.Web:

In addition to this, these assemblies work in medium trust server environments and are bin deployable. This essentially means that the assemblies do not need to be installed into the GAC (Global Assembly Cache). You can simply add a reference to the assemblies, and you are done.

The System.Web.Abstractions.dll and System.Web.Routing.dll assemblies are stored in [Installation Directory]\Reference Assemblies\Microsoft\Framework\v3.5. Note: [Installation Directory] in this case is generally [%Program Files%].

The example in this article stores these files in the "Reference_Assembly" directory. Once added, you need to reference the three core assemblies in your application by using the Project/Add Reference dialog. Refer to the figure below:

Note: The classic WebForms are located in the "ClassicWebForms" folder, and the ASP.NET MVC Views are located in the "Views" folder.

As mentioned earlier, the ASP.NET MVC follows certain conventions (doing things in a prescribed way). One of the core conventions of ASP.NET MVC is the naming of the directories where the project's Controllers and Views are kept.

For this example, we will use the directories "Controllers" and "Views" for storing the respective controllers and views.

We create the HomeController.cs and put it in the Controller directory in App_Code. In big solutions, the controller may belong to its own respective assembly. The HomeController view file Index.aspx is located in the Views/Home folder.

Hosting an ASP.NET MVC web application: If you or your web hosting provider have access to your web server's settings, a wildcard script map can be created in order to have full routing support. A wildcard script map enables you to map each incoming request into the ASP.NET framework. Be aware that this option passes every request into the ASP.NET framework (even images and CSS files!), and may have performance implications. If you do not have access to the web server's settings, you can modify the route table to use file extensions. Instead of looking look like this: /Home/Index, URLs would look like this: /Home.aspx/Index. This way, no configuration of the web server is required. It is, however, necessary to make some modifications to the application's route table.

You do not have to configure anything if your IIS 7.0 server is operating in Integrated mode.

Creating a wildcard script map in IIS 7.0

Here is how you can enable a wildcard script map in Internet Information Services 7.0:

Launch the IIS Manager.

In the Connections tree-view, select an application.

In the bottom toolbar, make sure that the Features view is selected.

Double-click on the Handler Mappings shortcut.

In the Actions window, click on the Add Wildcard Script Map button.

Enter the path to the aspnet_isapi.dll file, which is usually located in: %windir%Microsoft.NETFrameworkv2.0.50727aspnet_isapi.dll.

Enter the name ASP.NET MVC.

Click on the OK button.

After doing this, any request for this specific web site will be executed by the ASP.NET engine.

Creating a wildcard script map in IIS 6.0

Here is how you can enable a wildcard script map in Internet Information Services 6.0:

Launch the Internet Information Services IIS Manager.

Right-click on a web site and select Properties.

Select the Home Directory tab.

Near Application settings, click on the Configuration button.

Select the Mappings tab.

Near Wildcard application maps, click on the Insert button.

Enter the path to the aspnet_isapi.dll file, which is usually located in %windir%Microsoft.NETFrameworkv2.0.50727aspnet_isapi.dll.

Uncheck the Verify that file exists checkbox.

Click on the OK button.

After following these steps, any request for this specific web site will be executed by the ASP.NET engine.

There is actually one difference between a native MVC web application project and your “upgraded” WebForms project. When you want to add a view template using the Add New Item dialog, Visual Studio won’t offer you an MVC View Page or any of the other MVC-specific items. And, when you right-click inside an action method, you don’t get the option to add a view. That’s because Visual Studio doesn’t realize you’ve got an ASP.NET MVC project.

To resolve this, you need to add a project type hint for Visual Studio. This is pretty simple if done with a few precautions.

Caution: Before venturing out for this, backup your project file (i.e., the one with the .csproj extension). If you edit the project file incorrectly, Visual Studio will be unable to open it.

In Solution Explorer, right-click your project name and choose Unload Project. Right-click the project name again, and choose Edit <yourproject>.csproj (replace the angled bracket content with your project name). You’ll now see the .csproj XML file. Find the <projecttypeguids> node which contains a semicolon-separated series of GUIDs, and add the following value in front of the others: {603c0e0b-db56-11dc-be95-000d561079b0};. Do not add any extra spaces or line breaks. If you don’t want to type in the GUID by hand, you can copy and paste it from the corresponding section of any valid ASP.NET MVC .csproj file you might have elsewhere. Save the updated .csproj file. Then, reload the project by right-clicking its name in Solution Explorer and choosing Reload Project.

If you get the error “This project type is not supported by this installation”, then either you have mistyped the GUID, or you haven’t installed the MVC Framework on your PC.

If you get the error “Unable to read the project file”, then simply click OK and choose Reload Project again. It seems to sort itself out, for reasons unknown to me.

You should now find that MVC-specific items appear in the Add New Item dialog, alongside the usual WebForms items, and you’ll be able to right-click inside an action method and choose Add View.

The following points should be taken care of while migrating an existing ASP.NET application to ASP.NET MVC:

Plan the process. Do not migrate at one go. Take an area and do a migration.

ASP.NET MVC2 (preview) allows applications to be created in "Areas". Areas provide a means of grouping controllers and views to allow building subsections of a large application in relative isolation to other sections.

Design routes for your new areas.

Migrate the views. WebForms applications have code-behind files, and this is discouraged in ASP.NET MVC. But in scenarios like this, I think you can keep the code-behind files and make the application work.

As a practice, create controllers and add actions for each of the events that is raised in the view.

Since abstraction is the key in the MVC design, you can write Unit Test cases as the functionality is being migrated.

For Unit Tests, abstract away all concrete dependencies in the code-behind and move those to the controller. Some of the dependencies are Session, Cache, HttpContext (related methods), Repository etc.

Once the test passes, use your good judgement whether you want to get away with the code-behind.

In case you are migrating your existing site to ASP.NET MVC, you may require to support the existing URLs that your customers may have bookmarked. There may be many reasons for this. Your customer may be a premium customer and you don't want' to make him unhappy just because you upgraded your site.

I was aware of this technique, but the example was adapted from Mike's website. So, due credit to him for this. Please find the referenced URL in the References section.

This can be done by creating a custom route. All routes derive from RouteBase. Derive your legacy route from RouteBase and override the GetRouteData(..) method. For example, say you have a URL http://yourdomain.com/profile.aspx?id=specialid. Here's a rudimentary example to understand the process:

Now, if a request is made to an old URL, such as http://mysocialnetwork.com/profile.aspx?id= 101, it is automatically redirected to http://mysocialnetwork.com/profile/rajesh with the correct header sent to the user agent. You can check this through an HTTP debugger like Fiddler.

The harmony between Web Forms and ASP.NET MVC wasn't as complicated as I thought. Overall, it was an excellent learning, and would hopefully be useful in some of the migration projects which I may do in future.

Some of the readers may not agree with some points like the use of code-behind files in ASP.NET MVC. Even I am not in favor of it. But migration is one area where this has its place and leaves the choice with the developer/designer to migrate it based on need and time constraints. So, please don't take this as "word written on stone". Use your good judgment.