I am assuming that the convention routing would be added to the route table first because it is getting registered in the global.asax file like this
RouteConfig.RegisterRoutes(RouteTable.Routes);
Now I have a route like this in the route.config
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapMvcAttributeRoutes();
}
and I have an attribute route like this
[Route("students/{id?}")]
public ActionResult Index(int? id)
{
return View(id);
}
Now when I use the URL
localhost:4200//students
The students route is getting called successfully but when I use the route like this
localhost:4200//students/40
I get error, I don't know the reason why. When I remove the route from RouteConfig class I am able to call it successfully.
Can anyone explain me why and how?
In your original example the URL localhost:4200//students/40
is being matched to the url: "{controller}/{action}/{id}",
convention-based route template.
But since there is no action called 40
it will fail.
Now because it has already matched a route, it will not check any further for other matches so you will end up with Not Found error.
In Asp.Net MVC, routes are called in the order they are added to the routing table. First match wins and it does not do any further checks.
Targeted attribute routes are usually added before more general convention based routes to avoid route conflicts like the one experienced in your example.
public static void RegisterRoutes(RouteCollection routes) {
//Attribute routes
routes.MapMvcAttributeRoutes();
//Convention-based routes.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}