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.
Where we need this? What is the real world use of this?
First every one will have doubts in understanding areas feature. I want to explain a problem i have faced with one of my projects.
In ASP.NET MVC 1.0, i had a project which has at least 70-80 views. There was an Admin module which has so many sub modules. We had no inbuilt support for group view into Sub views folder inside a main folder.
For example I have a project which has the following folder structure.
/Admin
/Blog
/User
I wanted to create some sub views inside the /Admin main view folder and should be able to access it through URL
just like:
/Admin/Config/MyView will take view MyView.aspx from /Admin/Config/MyView.aspx
/Admin/Config/Details will take view Details.aspx from /Admin/Config/Details.aspx
and in blogs folder i want to create a Child View which is called “Posts”, so that i can group all my posts information related views,models and controllers under the /Blogs.
/Blogs/Posts/ViewPosts
But grouping like this or arranging your project is not supported on the ground in ASP.NET MVC 1.0. ASP.NET MVC 1.0 does not directly supports using Child Controllers and Views, or grouping large projects in different folders. So i am stuck there with my project tasks.
We have some 3rd party or extensions or samples made by some of the Microsoft Solution Experts. They have implemented it by extending the ASP.NET MVC 1.0 classes. Which didn’t go well with my project. Still we are maintaining a 30 or more views in single Controller and more than 1000’s of lines in each controller.
Which was a bad idea. But we had no other options, R&D didn’t go well with it. Deadlines were near, So we went on with current structure. In the future we will make changes to our project, since ASP.NET MVC 2.0 is about to come out soon. Right now delivery on time is important to us.
I hope you understood what i am trying to explain.
ASP.NET MVC 2 will include built-in support for breaking apart a large MVC application into “areas”.
To quote ScottGu:
Areas provide a means of grouping controllers and views to allow building subsections of a large application in relative isolation to other sections. Each area can be implemented as a separate ASP.NET MVC project which can then be referenced by the main application. This helps manage the complexity when building a large application and facilitates multiple teams working together on a single application together.
There is a detailed walkthrough on MSDN for creating an Areas application using multiple projects. You create a parent project (MvcAreasMultiProject) and two sub-projects (Accounts and Store).
- The parent project includes the usual Home and Account controllers (and associated views).
- The Store project includes a Product controller (and its views).
- The Accounts project maintains an Accounts controller (and its views).
Notice the “s” on the Accounts controller name – there is an Account controller and an Accounts controller in the application – we’ll come back to that.
Inside the parent project, use the AreaRegistration class to magically register all the routes in all child projects.
[code lang=”csharp”] <pre>public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
<strong>AreaRegistration.RegisterAllAreas();</strong>
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
}</pre>
[/code]
The AreaRegistration class will scan assemblies looking for types derived from AreaRegistration. It will instantiate these types and execute a method to give the the child projects a change to register their own routes. For example, the Accounts sub-project registers it’s routes with the following code:
[code lang=”csharp”]
<pre>public class Routes : AreaRegistration
{
public override string AreaName
{
get { return "Accounts"; }
}
public override void RegisterArea(
AreaRegistrationContext context)
{
context.MapRoute(
"Accounts_Default",
"Profile/{action}/{id}",
new { controller = "Accounts",
action = "Index", id = "" }
);
}
}</pre>
[/code]
With routes in place you can now generate links that reach specific areas. The following snippet creates a link to the Accounts controller in the Accounts sub-project…
[code lang=”csharp”]
<pre><%= Html.ActionLink("Accounts", "Index", "Accounts",
new { area = "accounts" }, null)%></pre>
[/code]
… while this one links to the Account controller in the parent project…
[code lang=”csharp”]
<pre><%= Html.ActionLink("Log On", "LogOn", "Account",
new { area = "" }, null)%></pre>
[/code]
Conflict!
What happens if two of the projects have a controller with the same name? For instance, if both the parent project and the Accounts project have an AccountController (with no “s” on Account).
If you try to reach the AccountController inside the Accounts area – everything should work. This is because the AreaRegistrationContext used to register routes for the Accounts area is automatically adding a namespace value to restrict the controller search. It’s like using the following code:
[code lang=”csharp”]
<pre>namespace Accounts
// ^^
// the namespace of the area registration type
// is used by default when mapping routes
{
public class Routes : AreaRegistration
{
public override string AreaName
{
get { return "Accounts"; }
}
public override void
RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Accounts_Default",
"Profile/{action}/{id}",
new { controller = "Account",
action = "Index", id = "" },
null,
new string[] { "Accounts" }
// ^ this is explicitly specifying
// the namespace as "Accounts",
// but "Accounts" is the
// default, so this isn’t needed
);
}
}
}</pre>
[/code]
Note that the AccountController doesn’t have to live in the root Accounts namespace. It can live further down the hierarchy (like Accounts.Controllers.AccountController) and the factory will still find it.
The child area is in good shape, but a problem can occur if you try to reach the AccountController in the parent project. If the routes for the parent project were not given a any namespace values (which they aren’t by default), then the default controller factory will become angry and throw an exception at runtime.
MvcAreasMultiProject.Controllers.AccountController
Accounts.Controllers.AccountController
The easiest solution is to include the namespace(s) for your parent project controllers when registering routes in the parent area.
[code lang=”csharp”]
<pre>routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" },
null,
// namespaces ->
new string[] { "MvcAreasMultiProject" }
);</pre>
[/code]
Summary
- You need to specify namespaces when registering routes if you have duplicate controller names.
- The AreaRegistrationContext will automatically include a namespace value when registering routes in a child area. The namespace is the same namespace as the type used to register routes.
Discover more from Cloud Distilled ~ Nithin Mohan
Subscribe to get the latest posts sent to your email.