Single Project Areas With ASP.NET MVC 2 Preview 1

UPDATEThis post is now obsolete. Single project areas are a core part of ASP.NET MVC 2.

Preview 1 of ASP.NET MVC 2 introduces the concept of Areas. Areas provide a means of dividing a large web application into multiple projects, each of which can be developed in relative isolation. The goal of this feature is to help manage complexity when developing a large site by factoring the site into multiple projects, which get combined back into the main site before deployment. Despite the multiple projects, it’s all logically one web application.

One piece of feedback I’ve already heard from several people is that they don’t want to manage multiple projects and simply want areas within  single project as a means of organizing controllers and views much like I had it in my prototype for ASP.NET MVC 1.0.

areas-folder-structure

Well the bad news is that the areas layout I had in that prototype doesn’t work right out of the box. The good news is that it is very easy to enable that scenario. All of the components necessary are in the box, we just need to tweak the installation slightly.

We’ve added a few area specific properties to VirtualPathProviderViewEngine, the base class for our WebFormViewEngine and others. Properties such as AreaViewLocationFormats allow specifying an array of format strings used by the view engines to locate a view. The default format strings for areas doesn’t match the structure that I used before, but it’s not hard for us to tweak things a bit so it does.

The approach I took was to simply create a new view engine that had the area view location formats that I cared about and inserted it first into the view engines collection.

public class SingleProjectAreasViewEngine : WebFormViewEngine {
    public SingleProjectAreasViewEngine() : this(
        new[] {
            "~/Areas/{2}/Views/{1}/{0}.aspx",
            "~/Areas/{2}/Views/{1}/{0}.ascx",
            "~/Areas/{2}/Shared/{0}.aspx",
            "~/Areas/{2}/Shared/{0}.ascx"
        },
        null,
        new[] {
            "~/Areas/{2}/Views/{1}/{0}.master",
            "~/Areas/{2}/Views/Shared/{0}.master",
        }
        ) {
    }

    public SingleProjectAreasViewEngine(
            IEnumerable<string> areaViewLocationFormats, 
            IEnumerable<string> areaPartialViewLocationFormats, 
            IEnumerable<string> areaMasterLocationFormats) : base() {
        this.AreaViewLocationFormats = areaViewLocationFormats.ToArray();
        this.AreaPartialViewLocationFormats = (areaPartialViewLocationFormats ?? 
            areaViewLocationFormats).ToArray();
        this.AreaMasterLocationFormats = areaMasterLocationFormats.ToArray();
    }
}

The constructor of this view engine simply specifies different format strings. Here’s a case where I wish the Framework had a String.Format method that efficiently worked with named formats.

This sample is made slightly more complicated by the fact that I have another constructor that accepts all these formats. That makes it possible to change the formats when registering the view engine if you so choose.

In my web.config file, I then registered this view engine like so:

protected void Application_Start() {
    RegisterRoutes(RouteTable.Routes);
    ViewEngines.Engines.Insert(0, new SingleProjectAreasViewEngine());
}

Note that I’m inserting it first so it takes precedence. I could have cleared the collection and added this as the only one, but I wanted the existing areas format for multi-project solutions to continue to work just in case. It’s really your call.

Now I can register my area routes using a new MapAreaRoute extension method.

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

    routes.MapAreaRoute("Blogs", "blogs_area", 
        "blog/{controller}/{action}/{id}", 
        new { controller = "Home", action = "Index", id = "" }, 
        new string[] { "SingleProjectAreas.Areas.Blogs.Controllers" });
    
    routes.MapAreaRoute("Forums", 
        "forums_area", 
        "forum/{controller}/{action}/{id}", 
        new { controller = "Home", action = "Index", id = "" }, 
        new string[] { "SingleProjectAreas.Areas.Forums.Controllers" });
    
    routes.MapAreaRoute("Main", "default_route", 
        "{controller}/{action}/{id}", 
        new { controller = "Home", action = "Index", id = "" }, 
        new string[] { "SingleProjectAreas.Controllers" });
}

And I’m good to go. Notice that I no longer have a default route. Instead, I mapped an area named “Main” to serve as the “main” project. The Route URL pattern there is what you’d typically see in the default template.

If you prefer this approach or would like to see both approaches supported, let me know. We are looking at having the single project approach supported out of the box as a possibility for Preview 2.

If you want to see this in action, download the following sample.

What others have said

Requesting Gravatar... Pita.O Jul 31, 2009 7:12 AM
# re: Single Project Areas With ASP.NET MVC 2 Preview 1
Phil,
What can I say?! Thank you, again. This is great news. Am not sure if anyone has thought about how these projects (areas) will manage security across their boundaries ... like session or authentication tokens: for instance, are areas also authorization boundaries, do user have to reauthenticate on crossing area boundaries, do child areas inherit token from the parent, etc. Is this configurable behavior? I like configurable.
Requesting Gravatar... Duncan Godwin Jul 31, 2009 7:36 AM
# re: Single Project Areas With ASP.NET MVC 2 Preview 1
My first reaction when I heard about areas being for multiple projects was that I would want this to work in single projects as well. This is partly driven by a desire to have as few a projects in a solution as possible because it makes it easier to move things around.

So, for me I would like to see this in the box for MVC 2.

Requesting Gravatar... Insomniak Dec 23, 2009 3:48 AM
# re: Single Project Areas With ASP.NET MVC 2 Preview 1
Hi Phil,

Thanks for all your job !
The code sample at the end of your post is broken.
Requesting Gravatar... Jim Ralph Dec 31, 2009 9:37 AM
# re: Single Project Areas With ASP.NET MVC 2 Preview 1
Thanks for this. Your sample "zip" is invalid, though, which is frustrating, and your contact page is broken. however, with your hard drive crashes I imagine that is the least of your worries. Good luck! When you might be able to get the code sample back on line, that would be a great boon.
Requesting Gravatar... Sunil Jan 07, 2010 2:41 PM
# re: Single Project Areas With ASP.NET MVC 2 Preview 1
Hey phil,

your logic look cool, It will great if you could upload example prototype to acheive areas in MVC1.0

Thanks
Sunil
Requesting Gravatar... notebook adaptör Feb 10, 2010 4:27 PM
# re: Single Project Areas With ASP.NET MVC 2 Preview 1
Hi Phil,

Thanks for all your job !
Requesting Gravatar... mousedoc Apr 15, 2010 12:26 AM
# re: Single Project Areas With ASP.NET MVC 2 Preview 1
Removing multi-project areas was a huge step backwards for team development.
Requesting Gravatar... Rodrigo Caballero Oct 17, 2010 7:02 AM
# re: Single Project Areas With ASP.NET MVC 2 Preview 1
Hi Phil, I tried to make work the multiproject areas from msdn at
msdn.microsoft.com/.../ee307987%28VS.100%29.aspx

and after one hour of searching why it wasn't working I realized that multiple project areas are no longer supported on the official ASP.NET MVC 2 release.

Can you tell me why it is not supported? and, Are there any way or guide to make a more robust architecture based on MVC?

regards

Comments have been closed on this topic.