Simple Modularity Through Areas In ASP.NET MVC

In this article, you will learn about simple modularity through areas in ASP.NET MVC.

The needs and requirements of many applications can change and evolve over time and managing these changes can often be difficult. This is one of the reasons that it’s important to be able to try and build modular applications that can easily separate all of the areas of your application and allow you to easily toggle them on or off for different client needs.

This article will provide an introduction to the areas for creating a very basic, modular ASP.NET MVC Application. The goal will be to allow you to separate all of the independent modules that might be present in your Application, using Areas as well as the ability to easily toggle these on and off, style them independently and more.

What are ASP.NET MVC Areas?

Areas can be thought of as modules within the context of MVC Applications. They provide a logical grouping of Controllers, Models, Views and any other folders or files that might be necessary for your module.

areas

Areas themselves are housed within a top-level. Areas folder within your MVC Application and each individual area will function as its own self-contained module. Areas allow the developers to write more modular, maintainable code that by definition would be cleanly separated from the parent Application, other modules and areas.

Getting Started

In this example, we will construct a parent Application that will consist of three different modules, each with its own Controllers, Views, Routing and anything else that we desire.

First, create a new ASP.NET Web Application project.

create

Ensure that you are creating an empty project for this example and including the appropriate references for MVC,

Empty project

This Application will consist of a parent and base controller, where all the child modules live.

This will allow you to easily define your layout, any navigation to access your child modules and any CSS, JavaScript and other references that your Areas will rely on. You’ll want to create a new controller, which for the purposes of this example will be called ParentController,

  1. namespace ModularityExample.Controllers    
  2. {  
  3.     public class ParentController : Controller  
  4.     {  
  5.         public ActionResult Index()  
  6.         {  
  7.             return View();  
  8.         }  
  9.     }  
Next, you’ll want to create a View for this Action. Just right-click it and choose Add View in the context menu that appears. After creating it, decorate it as you like, here’s the example I am using:
  1. <!DOCTYPE html>    
  2. <html>    
  3.     <head>  
  4.         <meta name="viewport" content="width=device-width" />  
  5.         <title>Base Parent Controller</title>  
  6.     </head>  
  7.     <body>  
  8.        <h1>Parent Content</h1>  
  9.     </body>  
  10. </html>   
In the next steps, we will tackle creating and building the modules within the Application.

Building your Modules / Areas

You’ll next want to create three separate modules within your example Application. Thankfully, the process of building these modules is incredibly easy and doesn’t take more than just a few seconds.  
  1. Right-click on your project in the Solution Explorer.
  2. Choose the Add > Area… option that appears in the context menu.
  3. Type the name of the Area that you want to use.

That’s it! Visual Studio will take care of scaffolding out everything that you need, to get started. For the purposes of this example, I’ve chosen to create three different Areas for colors: Red, Blue and Yellow, shown below:

area

Let’s take a bit of time to figure out exactly what is contained within each of the areas that we created. As I mentioned previously, each of the Areas is going to resemble a tiny MVC project.

  • Controllers
  • Views
  • Models
  • An AreaRegistration File

All of these should be fairly familiar to anyone that has worked with MVC previously except for perhaps the last AreaRegistration file. These AreaRegistration files are going to be found within each MVC Area created and they handle wiring up routing calls to the Area itself, shown below:

  1. namespace ModularityExample.Areas.Blue    
  2. {  
  3.     public class BlueAreaRegistration : AreaRegistration   
  4.     {  
  5.         // An override to indicate the name of the Area itself  
  6.         public override string AreaName   
  7.         {  
  8.             get   
  9.             {  
  10.                 return "Blue";  
  11.             }  
  12.         }  
  13.   
  14.         // A method to register the appropriate routes within  
  15.         // parent MVC Application  
  16.         public override void RegisterArea(AreaRegistrationContext context)   
  17.         {  
  18.             context.MapRoute(  
  19.                 "Blue_default",  
  20.                 "Blue/{controller}/{action}/{id}",  
  21.                 new { action = "Index", id = UrlParameter.Optional }  
  22.             );  
  23.         }  
  24.     }  
  25. }  
The RegisterArea method is going to be triggered by the parent MVC Application when the Application is initially launched. You can see this in Action within the Global.asax file, located at the root of your MVC project.
  1. public class MvcApplication : System.Web.HttpApplication    
  2. {  
  3.         protected void Application_Start()  
  4.         {  
  5.             // This RegisterAllAreas() method will trigger   
  6.             // the RegisterArea in each of your individual areas  
  7.             AreaRegistration.RegisterAllAreas();  
  8.             RouteConfig.RegisterRoutes(RouteTable.Routes);  
  9.         }  
  10. }  
Next, you can build a controller for each of the Areas that you just created. It’s just as easy as you might expect and can be done by right-clicking on the Controllers folder within an Area and choosing New > Controller.

For the sake of simplicity, we will model them similarly to our ParentController that was previously created. Just use the Add View option and let ASP.NET’s scaffolding take care of the rest,
  1. namespace ModularityExample.Areas.Blue.Controllers    
  2. {  
  3.     public class BlueController : Controller  
  4.     {  
  5.         public ActionResult Index()  
  6.         {  
  7.             return View();   
  8.         }   
  9.     }   
  10. }  
You’ll probably want to define a very basic View for your Index actions so that you actually have something to access. After doing this, you should be able to run your Application and access each of the areas directly based on their respective routes (e.g. localhost/Parent, localhost/Blue, etc.).

This is not useful.Thus, let’s build a Layout and a Navigation area to help make these areas more defined. Within the Parent Application, create a Layout page called _Layout.cshtml under the Views > Shared directory and paste the following code into it:
  1. <!DOCTYPE html>    
  2. <html>    
  3.     <head>  
  4.         <meta name="viewport" content="width=device-width" />  
  5.         <title>Modularity Testing</title>  
  6.     </head>  
  7.     <body>  
  8.         @Html.Partial("_Navigation")  
  9.         <div>  
  10.             @RenderBody()  
  11.         </div>  
  12.     </body>  
  13. </html>    
Next, create another Partial View in the same directory called _Navigation.cshtml, that will be used to display our menu, shown below:
  1. <!-- Basic Styling (add into a master CSS file referenced in the Parent Layout later) -->    
  2. <style type="text/css">    
  3.    nav.menu { width100%background#0071BC; }  
  4.    nav.menu a { display: inline-blockwidth100pxpadding6pxtext-aligncentercolor#FFFtext-decorationnone; }  
  5.    nav.menu a:hover { background#0093DE;}  
  6. </style>  
  7.   
  8. <!-- Within the Navigation area, we will define our modules -->    
  9. <nav class="menu">    
  10.    <a href="@Url.Action("Index","Blue", new { area = "Blue" })">Blue</a>  
  11.    <a href="@Url.Action("Index","Red", new { area = "Red" })">Red</a>  
  12.    <a href="@Url.Action("Index","Yellow", new { area = "Yellow" })">Yellow</a>  
  13. </nav>   
Next, build another View called _ViewStart.cshtml within the Views folder of the Parent Application. This is going to be inherited for all of the Views within the Application and will help to provide a consistent look throughout. It should contain the following line in it:

@{ Layout = "~/Views/Shared/_Layout.cshtml";}

Finally, copy this same _ViewStart.cshtml file into all of the View folders within your Application (including your areas). At this point, if you are following along, your solution should look as shown below: 

areas

In the next section, we will look at adjusting the routing to place all of these modules below the Parent Controller.

Establishing Routing

Area routing can sometimes require a bit of thought, as you need to ensure that your routes are unique otherwise a later route may override a previously defined one and make navigating around a nightmare. In order to achieve the effect that we are looking for, we want our routes to all be housed under the Parent Application, as shown below:  
  • localhost/Parent This will function as a home page that will display all the individual modules available.
  • localhost/Parent/Blue
  • localhost/Parent/Red
  • localhost/Parent/Yellow

Note If this isn’t the preferred routing you are looking for, you can skip this phase as it is optional.

In order to implement this, we are going to go into each of our Areas and adjusting the routes. Open the AreaRegistration file within each of your areas and make the following changes within the RegisterArea method, as shown below:

  1. public override void RegisterArea(AreaRegistrationContext context)    
  2. {  
  3.        context.MapRoute(  
  4.              AreaName,  
  5.              String.Format("Parent/{0}/{{action}}/{{id}}",AreaName),  
  6.              new { controller = AreaName, action = "Index", id = UrlParameter.Optional }  
  7.        );  
  8. }  
You might be asking what is this all about? These routes will establish the default routing structure within your Application and will ensure that all of the individual modules are routed under the Parent Controller. This is by no means necessary, but for the purposes of this example, it’s happening.

If you run the project now, you will get the screenshot, shown below:

output
You can see the individual modules present in the menu. However, they aren’t dynamic… yet.

Hard-coded menu items are not too impressive. In the next section, we will define an approach to manage these modules, track those being used, and wrap up everything as expected.

Configuring Plug & Play

One of the reasons that you would want to adopt a modular approach like this might be the need to easily toggle the modules on and off for different clients. For the purposes of this example, we will do so, using the web.config (but you could easily use a database or any other data store).

Open the Global.asax.cs file and add the following section:
  1. public static class Application    
  2. {  
  3.         // Define a static Dictionary indicating the available areas  
  4.         public static Dictionary<stringbool> ModulesEnabled = new Dictionary<stringbool>();  
  5. }  
This will create a Dictionary that will store which modules have been enabled or disabled within your Application. Hence, you can add the appropriate logic within your View (specifically your _Navigation.cshtml file) on which areas you should display or not.

Next, you’ll want to open your web.config file and add each of your modules in and indicate if they are enabled or disabled as seen below,
  1. <appSettings>    
  2.     <!-- Access-specific Configuration Settings -->  
  3.     <add key="Blue" value="true" />  
  4.     <add key="Red" value="true" />  
  5.     <add key="Yellow" value="true" />  
  6. </appSettings>    
This section will allow you to easily change the settings for your application to enable or disabled certain modules. As I mentioned previously, this information can easily be stored within a database or some other data store.

Now, you actually need to read the values from your configuration file (or your preferred data source). To do this, you’ll return to the AreaRegistration.cs files for each of your Areas and add the following additional code within the RegisterArea method, shown below:
  1. public override void RegisterArea(AreaRegistrationContext context)    
  2. {  
  3.      // Determine if it is enabled or not  
  4.      Application.ModulesEnabled.Add(AreaName, Convert.ToBoolean(ConfigurationManager.AppSettings[AreaName]));  
  5.   
  6.      // Read from your configuration to determine if   
  7.      routes should be established  
  8.      if(Application.ModulesEnabled[AreaName])  
  9.      {  
  10.           context.MapRoute(  
  11.               AreaName,  
  12.               String.Format("Parent/{0}/{{action}}/{{id}}", AreaName),  
  13.               new { controller = AreaName, action = "Index", id = UrlParameter.Optional }  
  14.           );  
  15.      }  
  16. }  
After adding this to each of the individual areas, you just need to wrap the things up by adding the appropriate logic within your Navigation area (_Navigation.cshtml) to handle the displaying of the areas, shown below:
  1. <nav class="menu">    
  2.     @if (Application.ModulesEnabled["Blue"])  
  3.     {  
  4.          <a href="@Url.Action("Index","Blue", new { area = "Blue" })">Blue</a>  
  5.     }  
  6.     @if (Application.ModulesEnabled["Red"])  
  7.     {  
  8.          <a href="@Url.Action("Index", "Red", new { area = "Red" })">Red</a>  
  9.     }  
  10.     @if (Application.ModulesEnabled["Yellow"])  
  11.     {  
  12.          <a href="@Url.Action("Index", "Yellow", new { area = "Yellow" })">Yellow</a>  
  13.     }  
  14. </nav>   
And that’s basically it. If you wanted to toggle a particular section off, you would just need to visit the web.config to disable it (or you could make an interface within your Application to use a database to avoid any web.config changes),

<add key="Red" value="false" />

which yields,

output

If you wanted to add a bit more flair to any one of your specific modules, you can add some CSS (via a link or inline) into the _ViewStart.cshtml file, within a module as seen below:
  1. @{ Layout = "~/Views/Shared/_Layout.cshtml";}  
  2. <style type="text/css">    
  3.     /* Styles to override the layout (Yellow) */  
  4.     nav.menu { width: 100%; background: yellow; }  
  5.     nav.menu a { color: #000; }   
  6.     nav.menu a:hover { background: #FFF380; }  
  7. </style>    
If you were to do this to each of the modules, you would see the following, when running the Application:

application
What’s Next?

This post was obviously a way to implement the modularity within MVC Applications.I hope that it provided an introduction to ASP.NET MVC Areas and how they can be used within your Applications.

I’ll review a few other additions and configurations that you can make within an Application to further extend its flexibility (e.g. tracking the current location on the menu, applying aliases for the modules, module-based styles and more) within a series of follow up posts soon. If you wanted to get started, you can find this sample on GitHub at the following location,