Mixing ASP.NET Web Forms and ASP.NET MVC

You know that project that you started when Web Forms were still cool? And now you have to support it and that's just fine as long as it's only a couple of minor hacks every few months. But how about expanding the functionality? Adding forms?

Now that you have been using MVC for years, you must feel a little bit annoyed by being forced to switch your brain back to the old ways... But there's good news for you - mixing the approaches is doable. Not without certain pains, though.

When starting new web project in VS2013, there is actually an option to include the Web API and MVC interfaces. So we know that this is a legitimate scenario. But, with some tinkering, you can achieve the same in a VS2010 Web Forms application.

Converting to VS2013 and .NET 4.5 is probabbly a good idea, at least it was for us. There were some issues regarding Entity framework and binding to controls a well known component library, which we were stupid enough to use, but once we got past that, things were starting to look good and were able to use existing forms with little or no change. The main advantage with upgrading is that you get all the latest and greatest - especially NuGet and some hope of not having to go through such ordeal again. But that's a story for another time and remains to be seen.

The theory

Anyone who was ever touched by the glorifying efects of writing CGI's in C++ has probably come to several firmly anchored conclusions regarding web applications. One of them is certainly that a web application can be viewed as a black box, where by supplying input, you get some kind of output. And, before there were sessions, you could also count on the output being the same if the input was the same.

Disregarding that, the idea behind my devious plan was, that if you could separate the inputs from two applications, you could hammer them together into a single application, with some benefits, like sharing common infrastructure, EF models, business logic etc.

The practice

Using NuGet you are able to install the packages required to add MVC functionality to your Web App. Our approach was to make a new application in VS2103 and compare it to our old one imported from VS2010 and "reverse ingeneer" the differences one by one.

Start by upgrading the VS2010 project to VS2013. Project specific issues may arise, and you have to handle them yourself. Once that is done (your project runs in VS2013 using the latest .NET framework), you are ready to proceed.

Right click the project in Solution explorer and click Manage NuGet Packages. Now install Microsoft ASP.NET MVC. It's going to want some additional packages and you should agree happily. Now find Global.asax.cs and edit it so it looks like this:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("");    

    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.IgnoreRoute("{resource}.aspx/{*pathInfo}");
    routes.MapRoute("Default", 
"{controller}/{action}/{id}", 
    new { controller = "Home", action = "Index", id = "" });
    }

    void Application_Start(object sender, EventArgs e)
    {
    RegisterRoutes(RouteTable.Routes);
    }    
    …
}

Now can create the ./Controllers folder. Right clicking on it should give you an option to add new controller. When you do that, the ./Views folder is added automatically. Adding a view also creates the ./Views/Shared folder.

Now the only thing missing is the ./Views/Web.config file:

<?xml version="1.0"?>
<configuration>
    <configSections>
        <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
            <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
            <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
        </sectionGroup>
    </configSections>
    <system.web.webPages.razor>
        <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.1.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <pages pageBaseType="System.Web.Mvc.WebViewPage">
            <namespaces>
                <add namespace="System.Web.Mvc" />
                <add namespace="System.Web.Mvc.Ajax" />
                <add namespace="System.Web.Mvc.Html" />
                <add namespace="System.Web.Routing" />
            </namespaces>
        </pages>
    </system.web.webPages.razor>
    <appSettings>
        <add key="webpages:Enabled" value="false" />
    </appSettings>
    <system.web>
        <httpHandlers>
            <add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/>
        </httpHandlers>

        <pages validateRequest="false" pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=5.1.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=5.1.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=5.1.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
        <controls>
            <add assembly="System.Web.Mvc, Version=5.1.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
        </controls>
    </pages>
    </system.web>
    <system.webServer>
        <validation validateIntegratedModeConfiguration="false" />
        <handlers>
            <remove name="BlockViewHandler"/>
            <add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
        </handlers>
    </system.webServer>
</configuration>

Check the other Web.config files you might have in the project for old versions of System.Web and related libraries.

And that's about it! Happy MVCing.