ASP.NET MVC Areas–A Better Way To Structure The Application

Posted: April 14, 2012 in ASP.NET
Tags: , ,

This week I came across a problem related to structuring an ASP.NET MVC Web application one development team was facing. What they were trying to do was quite simple: to create a folder structure each having their own subfolders for View/Controller/Scripts/CSS etc. The application resources like JS/CSS etc. were not getting rendered properly. The issue was due to Web.config file lying under the subfolder, which when moved to the Views folder under that subfolder things went fine. The purpose of this post is not to discuss about the details of that problem and it’s solution.But to discuss about how we can easily structure our ASP.NET MVC Web application as per different modules, which is an obvious need for any large application.

ASP.NET MVC follows the paradigm of “Convention Over Configuration” and default folder structure and naming conventions works fine for a smaller application. But for relatively bigger one there is a need to customize.The framework also provides enough provisions for the same.You can have your own controller factory to have custom ways to creating the controller classes and custom view engine for locating the rendering the views. But if the requirement is to structure the application to different subfolders as per modules or subsites  I think the use of “Area” in ASP.NET MVC will be helpful to create a streamlined application.

You can add an Area to a ASP.NET MVC project in VS as shown below.

area1

area2

Here I have added an area named “Sales”. As shown in the figure below a folder named “Areas” is created with a subfolder “Sales”. Under “Sales” we can see the following

  • The standard folder of Models/Views/Controllers
    • A Web.config under the Views folder. This contains the necessary entries for the RazorViewEngine to function properly
  • A class named SalesAreaRegistration.

area3

The code (auto generated) for the SalesAreaRegistration class is shown below:

public class SalesAreaRegistration : AreaRegistration 
{ 
    public override string AreaName 
    { 
        get 
        { 
            return "Sales"; 
        } 
    }

    public override void RegisterArea(AreaRegistrationContext context) 
    { 
        context.MapRoute( 
            "Sales_default", 
            "Sales/{controller}/{action}/{id}", 
            new { action = "Index", id = UrlParameter.Optional } 
        ); 
    } 
} 

System.Web.Mvc.AreaRegistration is the abstract base class use registering the areas into the ASP.NET MVC Web Application. The method void RegisterArea(AreaRegistrationContext context) needs to be overriden to register the area by providing the route mappings. The class System.Web.Mvc.AreaRegistrationContext encapsulates the necessary information (like Routes) required to register the area.

In Global.asax.cs Application_Start event we need to RegisterAllAreas() method as shown below:

AreaRegistration.RegisterAllAreas();  

The RegisterAllAreas method looks for all types deriving from AreaRegistration and invokes their RegisterArea method to register the Areas.

Now with the necessary infrastructure code in place I have added a HomeController and Index page for the “Sales” area as shown below.

 

area4

Now I am trying to run the application and got the following error: [NOTE: This has nothing to do with areas but because I have two controllers with same type name i.e. HomeController]

Multiple types were found that match the controller named ‘Home’. This can happen if the route that services this request (‘{controller}/{action}/{id}’) does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the ‘MapRoute’ method that takes a ‘namespaces’ parameter.

The request for ‘Home’ has found the following matching controllers:

AreasDemo.Controllers.HomeController

AreasDemo.Areas.Sales.Controllers.HomeController

I have to change the Route Registration for the HomeController to avoid conflicts and provide the namespace information as shown below:

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

            routes.MapRoute( 
                "Default", // Route name 
                "{controller}/{action}/{id}", // URL with parameters 
                new { controller = "Home", action = "Index", id = UrlParameter.Optional },// Parameter defaults 
                new String[] { "AreasDemo.Controllers" } 
            ); 
}

Now I will add a link to the Sales area by modifying the _Layout.cshtml as shown below:

 
<li>@Html.ActionLink("Sales", "Index", "Home", new { area="Sales"},null)</li>

Here I am navigating to the area “Sales” from the main application so I have to provide area information with routeValues. The following overload is being used in the code above:

public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes);

For navigating within the “Sales” area however routeValues will not be required.

Comments
  1. Arindam Sarkar says:

    Looking forward a training on ASP.NET MVC in Gurukul…

  2. Sujeet Kumar says:

    very nice article

  3. Msbow says:

    on new String[] { “AreasDemo.Controllers” }

    Error 1 Named argument specifications must appear after all fixed arguments have been specified C:\Users\Msbow\Documents\Visual Studio 2012\Projects\MvcApplication14\MvcApplication14\App_Start\RouteConfig.cs 21 17 MvcApplication14

  4. […] ASP.NET MVC Areas – A Better Way to Structure The Application […]

  5. ferventcoder says:

    Got a quick question for you. My area / homecontroller / index is showing the index.cshtml from the main part of the app instead of the area specific one. How did you overcome this?

  6. Hamid says:

    I agree with splitting up the application into multiple areas. However, the fact that each area has its own model folder doesn’t make any sense to me. Model entities should normally be accessible throughout the application. For instance, “Product” entity is used by Admin, Sales, Customers, etc.

  7. kamal says:

    Clear concept ! Thanks..

  8. I enjoy what you guys are usually up too. This type of
    clever work and exposure! Keep up the fantastic works guys I’ve incorporated you guys to blogroll.

  9. I’m not that much of a online reader to be honest but your blogs really nice,
    keep it up! I’ll go ahead and bookmark your site to come back in the future. Many thanks

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.