Saturday, 25 April 2009

More Umbraco and ASP.NET MVC

Check out this post on the Umbraco forum for a better URL rewrite thanks to Immo.

Friday, 17 April 2009

Umbraco and ASP.NET MVC

I wanted to be able to implement an Umbraco site with some ASP.NET MVC pages so I set up a basic site as follows...

First off, I set up a clean Umbraco under IIS 7 (Classic mode). As it is classic mode I assume the setup should work with IIS 6.

My test site had a few basic pages provided through Umbraco and 2 MVC controllers - Home and Account. I can access the Umbraco pages through URLs like http://umbracomvc/installing-runway-modules.aspx and the MVC actions through URLs like http://umbracomvc/Account.aspx/LogOn.

I used a custom HttpHandler to process the MVC requests and the UrlRewriteModule that comes with Umbraco to redirect MVC requests to the custom handler.

Web.config

Make the following changes to web.config:

 1. Add the following under system.web/pages
<namespaces>
<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.Linq"/>
<add namespace="System.Collections.Generic"/></namespaces>
 2. Add the following under system.web/httpModules (more on this later)
<add name="RegisterRoutesModule" type="RegisterRoutesModule"/>
 3. Add the following under system.web/compilation/assemblies
<add assembly="System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Web.Abstractions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
mvc.ashx

This is the custom HttpHandler that will process all MVC requests. The actual route is passed to it on the query string - just like Umbraco passes routes to Default.aspx behind the scenes.

Create a file named mvc.ashx in the root of the Umbraco site and paste in the following text:

 

<%@ WebHandler Language="C#" Class="mvc" %>


using System.Web;

using System.Web.Mvc;

 

public class mvc : MvcHttpHandler

{

    protected override void ProcessRequest(HttpContext httpContext)

    {

        string originalPath = httpContext.Request.Path;

        string newPath = httpContext.Request.QueryString["mvcRoute"];

        if (string.IsNullOrEmpty(newPath))

            newPath = "/";

 

        HttpContext.Current.RewritePath(newPath, false);

        base.ProcessRequest(HttpContext.Current);

        HttpContext.Current.RewritePath(originalPath, false);

    }

}


RegisterRoutesModule.cs

We need to set up the MVC routes at some point. We can't do it in Global.asax as Umbraco has its own Global class so I used a custom HttpModule.

Create a file named RegisterRoutesModule.cs in the app_code folder and paste in the following text:

using System.Web;

using System.Web.Mvc;

using System.Web.Routing;

 

public class RegisterRoutesModule : IHttpModule

{

    public void Init(HttpApplication application)

    {

        RegisterRoutes(RouteTable.Routes);

    }

 

    public static void RegisterRoutes(RouteCollection routes)

    {

        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

 

        routes.MapRoute(

            "Default",

            "{controller}.aspx/{action}/{id}",

            new { action = "Index", id = "" }

          );

 

        routes.MapRoute(

          "Root",

          "",

          new { controller = "Home", action = "Index", id = "" }

        );

    }

 

    public void Dispose()

    {

 

    }

}


Views and Controllers

We need some Views and Controllers so create a new ASP.NET MVC project. Copy the Views folder from the new project into the root of the Umbraco site and copy the Controllers folder into the app_code folder of the Umbraco site.

URL Rewriting

Finally we need to redirect incoming requests for MVC pages to the MVC handler. Open up config/UrlRewriting.config in Umbraco and add the following entries:

<add name="MVC_Home_Rewrite"
virtualUrl="^~/Home.aspx/(.*)"
rewriteUrlParameter="ExcludeFromClientQueryString"
destinationUrl="~/mvc.ashx?mvcRoute=/Home.aspx/$1"
ignoreCase="true" />

<add name="MVC_Account_Rewrite"
virtualUrl="^~/Account.aspx/(.*)"
rewriteUrlParameter="ExcludeFromClientQueryString"
destinationUrl="~/mvc.ashx?mvcRoute=/Account.aspx/$1"
ignoreCase="true" />

That should be everything. Next I want to create an Umbraco macro that calls MVC actions via a UserControl...