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

default route with id does not working in asp.net core


This is my controller:

public class HomeController : Controller
{
    public IActionResult Index()
    {
        var route = Request.Path.Value;
        return View("index" as object);
    }

    [HttpGet("{id}")]
    public IActionResult Index(int id)
    {
        return View("index id" as object);
    }
}

This is my route:

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

url : /1 -> return index with id
url : /Home/Index/1 -> return index without id

I don't understand why?


Solution

  • You're using mixed routing - you've got conventional routing for the first action and attribute routing for the second.

    When you navigate to /1, you hit the second action with the id parameter, because it's been set to use attribute routing for a path of /{id} (by using [HttpGet("{id}")]): Attribute routing overrides conventional routing.

    When you navigate to /Home/Index/1, you hit your first action without the id parameter, simply because the other action you have is no longer a match given that it's been set to use attribute routing (/{id}), so it no longer matches /Home/Index/1 at all. With your conventional routing template from UseMvc, you've said that id is optional and so the match is still valid.

    In order to achieve what you're looking for, you can use attribute routing exclusively for this controller. Here's what that would look like:

    [Route("/")]
    [Route("[controller]/[action]")]
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            ...
        }
    
        [HttpGet("{id}")]
        public IActionResult Index(int id)
        {
            ...
        }
    }
    

    The addition of the two [Route(...)] attributes here adds support for the following two routes:

    1. / and /{id}.
    2. /Home/Index and /Home/Index/{id}.

    [controller] and [action] are placeholders that represent the name of the controller and action respectively - You could also just use the literal values Home and Index if you'd prefer something more fixed.

    You don't necessarily need both [Route(...)] attributes, but the / version ensures the root of the site also matches the same controller/action pair.