Areas make use of the Routing mechanism in ASP.NET, so if you are not very clear on how routing works, try this article first.
Working with Areas
Essentially Areas are used for better management of large projects. For example, we may have an ecommerce application that has Admin, Store and Billing areas where Admin manages backend work like creating categories, catalogs, prices etc. Store is the end user portal for searching, selecting adding to cart and Billing is where all invoicing and shipping is managed.As we can see, each of these sections are pretty big functionality wise and can be easily segregated into areas. Let’s see how we can get started with Areas.
Adding an area in a MVC project
1. In a new MVC 4 Application, right click on the project and select Add > Area2. We’ll name the Area ‘Admin’
3. This adds the Areas folder to the project with the following hierarchy
4. Notice the AdminAreaRegistration.cs file. The generated class looks as follows
public class AdminAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Admin";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}
As we can see from the class, it derives from AreaRegistration class and override the AreaName property and the RegisterArea property.
a. The AreaName returns the name we provided while creating the Area.
b. The RegisterArea registers a new route for the Area that begins with ‘Admin’ (the name of the Area) by calling the MapRoute method of the context.
5. Next we open the Global.asax to get an idea of route ordering. Notice that AreaRegistration.RegisterAllAreas() is called before RouteConfig.RegisterRoutes(). What this essentially means is that the above Route will get registered before the default ASP.NET routes are installed. This is important because you can have calls to /HomeController/Index/ and /Admin/HomeController/Index. If /HomeController/Index gets registered first, then navigating to /Admin/HomeController/Index will be routed to the wrong controller class.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
}
Now that we have added a new Area, let’s add a controller and view to it. To test the routing out, we’ll call our controller inside the new area also called HomeController.
Next we add a new View called Index in the Areas\Admin\View\Home folder, a _ViewStart.cshtml under the Areas\Admin\View\ folder and a _Layout.cshtml in the Areas\Admin\View\Shared folder.
@{
ViewBag.Title = "Index";
}
<h2>Areas\Home\Index</h2>
Listing 3 Index.cshtml
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
Listing 4 _ViewStart.cshtml
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Admin Area</title>
</head>
<body>
<h1>Admin Area</h1>
<div>
@RenderBody()
</div>
</body>
</html>
Listing 5 _Layout.cshtml
Now let’s run the application. Before even getting to the home page, we end up with the following YSoD (Yellow Screen of Death)
Don’t you just love the verbosity of the exception? Well in plain speak it means - if you are going to have two controllers called HomeController, you have to specify their namespace while registering the routes.
The AreaRegistrationContext is supposed to have used the namespace while registering the route in the RegisterArea method that we saw earlier. That leaves the default route registration which does not have namespaces defined. Let’s get to App_Start\RouteConfig.cs and add the namespaces parameter to the MapRoute method call. We pass the “MvcAreasDemo.Controllers” namespace as the parameter of our default HomeController.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new {
controller = "Home",
action = "Index",
id = UrlParameter.Optional },
// add the explicit namespaces param when using Areas
namespaces: new [] { "MvcAreasDemo.Controllers" }
);
}
With the above change, when we run the application we see the default MVC template page on launch
Now if we navigate to the Admin/Home URL, we see the Admin area’s Home Controller in action.
Adding another Area
Now that we’ve added a new Area and things are working fine, how do we know if a second area will not cause routing conflicts? Well, as mentioned above, the AreaRegistrationContext internally passes the NameSpace to the Route Configuration. Thus multiple areas registered via the AreaRegistrationContext do not cause a problem. Just to make sure, add another Area called Store and add a HomeController to it (do not copy from Admin area or make partial classes between Admin and Store areas). You can copy the views over and update them appropriately.Run the application and navigate to all the three HomeControllers to see the pages separately.
Conclusion
To conclude, Areas are a useful construct if you are trying to build a large front-end system with clearly segregated areas of functionality. The only gotcha is that controllers sharing the same name across areas must have different namespaces and the default Route (if used) should explicitly provide the namespace parameter while configuring the Controller.Download the entire source code of the article (Github)
thanks, nice post.
ReplyDeleteNice Article !!
ReplyDelete