Areas in MVC allow you to separate your web application into segments, each with their own set of Controllers and Views, for better organization and intuitive access via routing. I decided to play with this MVC Areas feature in ASP.NET Core and thought I’d share my experience in case it might help others using this feature.
My first attempt to use this was to simply add the Areas folder to the root of my application, with a subfolder called Admin with the associated folders for Controllers, Models, and Views:
I added a simple AdminController to simulate a separate Administration section for the site, with two views that return raw content for testing:
public class AdminController : Controller {
// GET: /<controller>/
public IActionResult Index() {
return Content("You are in the Admin Index View!");
}
public IActionResult Other() {
return View("You are in the Admin Other View!");
}
}
I then visited each view, which seemed to be working fine:
However, moving on, I added simple view files for each action, linking to each one via both the ActionLink and new TagHelper syntax.
I created one for Index:
<h1>Index</h1>
<a asp-action="Other">Go to Other view (TagHelper)</a>
@Html.ActionLink("Go to Other view (ActionLink)", "Other")
And another for the “Other” View:
<h1>Other</h1>
<a asp-action="Index">Go to Index view (TagHelper)</a>
@Html.ActionLink("Go to Index view (ActionLink)", "Index")
And updated the controller to return these views:
public IActionResult Index() {
return View();
}
public IActionResult Other() {
return View();
}
However, this time, when I visited the same pages as before, I instead got an error that the Views could not be resolved:
An unhandled exception occurred while processing the request.
InvalidOperationException: The view ‘Index’ was not found. The following locations were searched:
/Views/Admin/Index.cshtml
/Views/Shared/Index.cshtml
Notice that my Admin area is not being searched, so I’m clearly missing a step, actually TWO steps.
First, I need to configure the routes for MVC in the Configure method of the Startup class to include areas:
app.UseMvc(routes => {
routes.MapRoute(name: "adminArea", template: "{area:exists}/{controller=Admin}/{action=Index}");
routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}");
});
Next, the controller itself needs to be decorated with an Attribute telling it the name (Folder) of the Area in which it resides:
[Area("Admin")]
public class AdminController : Controller
Now although going to the page no longer results in an error, there is a new issue with our links:
Although the ActionLink was smart enough to render the link to the other view, the TagHelper option seems lost and doesn’t render the same href attribute.
This one had me stumped for a while, but I knew something was wrong because I also noticed that Visual Studio was not syntax-highlighting the asp- helpers in the alternate color:
Fortunately, after a bit of searching I found a thread on the asp.net forums on this very issue, and it appears the fix is to add a _ViewImports.cshtml file to the root of the Views folder in the area, and ensure that the following line is included:
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
In my case I simply copied the same file from the root Views folder into the Area Views folder, and doing so immediately lit up the syntax-highlighting for the view:
And at last, both views correctly link to the appropriate actions:
Interestingly enough, the documentation for ASP.NET Core Areas makes no mention of this last bit, but there is a separate documentation page on TagHelpers which does explain how to enable them.
And with that we now have a simple separate area for site administration. Obviously we’ll want to add the Authorize attribute and protect this section, but we’ll leave that for a future discussion.
Until then, as always, I hope this was helpful and thanks for reading!
Enjoyed this post and/or found it useful?