Routing in ASP.NET Core MVC maps controllers and actions to paths in request URIs. Similar routing
happens in ASP.NET Framework MVC.
In ASP.NET Core MVC, when an action defines a route template starting with a "/", the route is considered absolute and the action is registered at
the root of the web application.
In such a scenario, any route defined at the controller level is disregarded, as shown in the following example:
<Route("[controller]")> ' This route is ignored for the routing of Index1 and Index2
Public Class HomeController
Inherits Controller
<HttpGet("/Index1")> ' This action is mapped to the root of the web application
Public Function Index1() As ActionResult
Return View()
End Function
<Route("/Index2")> ' The same applies here
Public Function Index2() As ActionResult
Return View()
End Function
End Class
The behavior can be found confusing and surprising because any relative action route is relativized to the controller route.
Therefore, in the vast majority of scenarios, controllers group all related actions not only in the source code, but also at the routing level.
In ASP.NET Framework MVC with attribute routing enabled via MapMvcAttributeRoutes
,
the mere presence of an absolute route at the action level will produce an InvalidOperationException
at runtime.
It is then a good practice to avoid absolute routing at the action level and move the "/" to the root level, changing the template defined in the
RouteAttribute
of the controller appropriately.
Exceptions
The rule only applies when all route templates of all actions of the controller start with "/". Sometimes some actions may have both relative and
absolute route templates, for example for backward compatibility reasons (i.e. a former route needs to be preserved). In such scenarios, it may make
sense to keep the absolute route template at the action level.