weblar83
weblar83

Reputation: 731

ASP.Net MVC Core 2 - Area Routing

I'm trying to implement an Area for Administrators within my ASP.Net MVC Core 2 application.

I have configured the route for the area as follows:

// Default route
app.UseMvc(routes =>
{
     routes.MapRoute(
         name: "default",
         template: "{controller=Home}/{action=Index}/{id?}");
});

// Admin area route
app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "admin",
        template: "{area=Admin}/{controller=Home}/{action=Index}/{id?}");
});

This all works pretty well.

This Admin area uses the same Layout as the main website albeit that the _ViewStart.cshtml lives in the Areas/Admin/Views directory but this still works fine.

The issue I'm having is with a navigation menu component which lives in the main site layout file and the href links in all anchors pointing to the wrong URL when inside the Admin area.

Say I have the following links:

<a asp-controller="Account" asp-action="Index">My Account</a>
<a asp-controller="Shopping" asp-action="Basket">Shopping Basket</a>
<a asp-controller="Admin" asp-action="Users">Manage Users</a>

When inside the Admin area, the links are now relative to the area and thus appear as if they were as follows:

http://localhost/Admin/Account/Index
http://localhost/Admin/Shopping/Basket
http://localhost/Admin/Admin/Users

Is there any nice way to make all of these links relative to the site root?

Upvotes: 1

Views: 6126

Answers (2)

David Liang
David Liang

Reputation: 21476

There are couple issues how you set things up in your application.

  1. You can't use app.UseMvc() twice. I think basically the last one will override your first setup. That's why you are seeing all links have /admin area prefix.
  2. When you want to generate a link to your user management under admin area, you should use asp-area instead, like <a asp-area="admin" asp-controller="users" asp-action="index">Manage Users</a>.

This is how I will setup areas.

Setup area route as well as the default route in Startup

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // The area routing setup has to come before your default routing!
    // Remember the order of these setups is very important!
    // Mvc will use that template as soon as it finds a matching! 

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "areaRoute",
            template: "{area:exists}/{controller=dashboard}/{action=index}/{id?}"
        );

        routes.MapRoute(
            name: "default",
            template: "{controller=home}/{action=index}/{id?}"
    );
}

Setup an admin base controller with [Area] annotation so that you don't have to specify that in all other controllers that should be under the admin area.

// Assume you have an Admin area under /Areas/Admin

namespace DL.SO.Web.UI.Areas.Admin.Controllers
{
    [Area("admin")]
    public abstract class AdminControllerBase : Controller
    {
    }
}

Controllers under admin area

// Dashboard controller. I know you have home controller inside 
// your admin area but they should work the same.

namespace DL.SO.Web.UI.Areas.Admin.Controllers
{
    public class DashboardController : AdminControllerBase
    {
        public IActionResult Index()
        {
           return View();
        }
    }
}

// Users controller. I know you have User(s) controller but I usually
// just keep the name of the controller singular.

namespace DL.SO.Web.UI.Areas.Admin.Controllers
{
    public class UserController : AdminControllerBase
    {
        public IActionResult Index()
        {
            return View();
        }
    }
}

Specify the area with anchor tag helper

// My habit is to always specify the area with the anchor tag helper.
// For public links (those are not under any areas):
//     I just pass empty string, like asp-area=""
// For links pointing to any controller under any area:
//     Just pass the area, like asp-area="admin"

// http://localhost/account
<a asp-area="" asp-controller="account" asp-action="index">My Account</a>

// http://localhost/shopping/basket
<a asp-area="" asp-controller="shopping" asp-action="basket">Shopping Basket</a>

// http://localhost/admin/user
<a asp-area="admin" asp-controller="user" asp-action="index">Manage Users</a>

// http://localhost/admin/dashboard
<a asp-area="admin" asp-controller="dashboard" asp-action="index">Admin Panel</a>

Upvotes: 5

Richard
Richard

Reputation: 96

You can edit the template for the URL to be displayed as preferred. i.e. change to

    template: "{controller=Home}/{action=Index}/{id?}");

Upvotes: 0

Related Questions