If you maintain an ASP.Net application for some time (as I do đ ), and also gained experience in developing using ASP.Net MVC, you probably want to implement any new features in MVC.
So I search for ways to add MVC to an existing ASP.Net application, and found a couple of solutions. However, they refer to older versions of MVC, so I’ll sketch here which steps are required for ASP.Net 4 and MVC 3.
The original information comes from these articles:
- Mixing ASP.NET Webforms and ASP.NET MVC
- ASP.NET WebForms and ASP.MVC and ASP.NET Dynamic Data Side By Side
- Migrating Classic ASP.NET to ASP.NET MVC 2 â Project
- SO answer
For some changes and additions, it’s easier if you already have an MVC project. If you do not, simply create a new “MVC3 Web Application” – all the required files will be generated.
Add assemblies
In your project, add references to the following assemblies:
- System.Web.Abstractions
- System.Web.Mvc
- System.Web.Routing
Unload project and edit project
Under <ProjectTypeGuids>, add the Guid “{E53F8FEA-EAE0-44A6-8774-FFD645390401};” to get MVC-specific “Add…” items in the context menu of the Solution Explorer, such as Add Controller and Add View. The line then reads
<ProjectTypeGuids>{E53F8FEA-EAE0-44A6-8774-FFD645390401};
{349c5851-65df-11da-9384-00065b846f21};
{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
In the first <PropertyGroup>, add the line
<MvcBuildViews>true</MvcBuildViews>
Add the end of the project file, add the MVC build target:
<Target Name="MvcBuildViews" AfterTargets="AfterBuild" Condition="'$(MvcBuildViews)'=='true'"> <AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" /> </Target>
Edit web.config
Under <system.web>/<compilation>, add the following assembly references
<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>
Under <system.web>/<pages>, add the following namespace declarations
<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>
Probably you also need to tweak assembly bindings
<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>
Project additions
In the project, add the folders Controllers and Views, and Views/Shared.
Copy the Views/web.config file from the other MVC application.
Edit Global.asax.cs
Add these using statements:
using System.Web; using System.Web.Mvc; using System.Web.Routing;
Add these lines to Application_Start():
AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes);
If you want to use the MVC Razor engine, also add:
ViewEngines.Engines.Add(new RazorViewEngine());
Add the methods RegisterRoutes() and RegisterGlobalFilters() as:
protected static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.IgnoreRoute("{resource}.aspx/{*pathInfo}"); routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "" } ); } protected static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); }
Personally, I prefer to have each action in a separate controller class, so I use the solution presented here:
routes.MapActionRoute( "Default", "{controller}/{action}/{oid}", new { controller = "Default", action = "Index", oid = UrlParameter.Optional }, new object { } );
Start Page
If you have a defined Start Page in the ASP.Net project, you will need to redirect there from the default MVC action:
namespace MyMvcWeb.Controllers { public class DefaultController : Controller { public ActionResult Index() { return Redirect(Url.Content("~/default.aspx")); } } }
Mixing Razor and WebForms views
Razor and WebForms are two different view engines, and cannot be mixed.*
If you want to use an ASP.Net master page for a WebForms MVC view, have a look at this SO answer.
As for WebForms, the ASP.Net master page derives from System.Web.UI.MasterPage, whereas an MVC master page derives from System.Web.Mvc.ViewMasterPage (which itself also derives from System.Web.UI.MasterPage).
As for Razor, master pages have been replaced by layout views. Both views and layout views derive from System.Web.Mvc.WebViewPage<T> which has no common base class with MasterPage.
*) Note that there is a solution to using Razor views in ASP.Net masterpages (Hanselman, Hawley, Baloch), but it looks a bit hacky and fragile – and, of course, unsupported đ
Debugging Routes
If things do not turn out as expected after implementing all these changes, have a look at the Route Debugger (original post, updated version).
Pingback: A jQuery Alternative for ACT CollapsiblePanelExtender | devioblog
Pingback: A jQuery Alternative for ACT HoverMenuExtender | devioblog
Pingback: A jQuery Alternative for ACT CalendarExtender | devioblog
Pingback: Stumbling Upon the “Not Pre-Compiled” Error Message | devioblog