Search code examples
c#asp.net-core.net-coreasp.net-core-routing

ASP.NET Core route of a controller and the index action


I'm trying to set a route of my controller while also be able to navigate the index without typing Index, here's what I tried:

My route configuration

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

Try #1

// My controller
[Route("panel/admin")]
public class MyController...

// My index action
public IActionResult Index()...

Problem: This doesn't work, all the actions become accessible at panel/admin so I get an error saying Multiple actions matched.
Even when setting the route of my index action to Route(""), doesn't change anything.

Try #2

// My controller
[Route("panel/admin/[action]")]
public class MyController...

// My index action
[Route("")]
public IActionResult Index()...

Here, the index route doesn't change, it stays panel/admin/Index.

What I want

I want to be able to access my index action when navigating to panel/admin and I also want my other actions to work with just their method names like panel/admin/UsersList.

Complete controller

[Route("panel/admin/[action]")]
public class MyController
{

    [Route("")]
    public IActionResult Index()
    {
        return View();
    }

    public IActionResult UsersList()
    {
        var users = _db.Users.ToList();
        return View(users);
    }

    // Other actions like UsersList

}

Thank you.


Solution

  • Reference Routing to controller actions in ASP.NET Core

    With attribute routes you have to be very specific about desired routes to avoid route conflicts. Which also means that you will have to specify all the routes. Unlike convention-based routing.

    Option #1

    [Route("panel/admin")]
    public class MyController {
    
        [HttpGet]
        [Route("")] //GET panel/admin
        [Route("[action]")]  //GET panel/admin/index
        public IActionResult Index() {
            return View();
        }
    
        [HttpGet]
        [Route("[action]")] //GET panel/admin/UsersList
        public IActionResult UsersList() {
            var users = _db.Users.ToList();
            return View(users);
        }
    
        // Other actions like UsersList
    }
    

    Option #2

    [Route("panel/admin/[action]")]
    public class MyController {
    
        [HttpGet] //GET panel/admin/index
        [Route("~/panel/admin")] //GET panel/admin        
        public IActionResult Index() {
            return View();
        }
    
        [HttpGet] //GET panel/admin/UsersList
        public IActionResult UsersList() {
            var users = _db.Users.ToList();
            return View(users);
        }
    
        // Other actions like UsersList
    }
    

    The tilde (~) in [Route("~/panel/admin")] overrides the route prefix on the controller.

    Tip

    While using multiple routes on actions can seem powerful, it's better to keep your application's URL space simple and well-defined. Use multiple routes on actions only where needed, for example to support existing clients.