Routing is a core concept in ASP.NET Core MVC that determines how incoming HTTP requests are mapped to the appropriate controller actions. It's the process of matching a URL to a specific piece of code that handles the request.
How Routing Works
ASP.NET Core uses a routing system that consists of one or more route templates. These templates define the URL patterns your application will recognize. When a request arrives, the routing engine tries to match the URL against these templates.
The Default Routing Convention
By default, ASP.NET Core MVC applications are configured with a convention-based router. The standard route template is often defined in the Program.cs (or Startup.cs in older versions) file:
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
Let's break down this default route template:
{controller=Home}: This segment matches the controller name. If no controller is specified in the URL, it defaults to theHomecontroller.{action=Index}: This segment matches the action method name within the controller. If no action is specified, it defaults to theIndexaction.{id?}: This segment is optional (indicated by the?). It's typically used to pass an identifier, such as a primary key, to the action method.
Example URL Matching
Consider the default route template "{controller=Home}/{action=Index}/{id?}":
- A request to
/will map toHomecontroller'sIndexaction. - A request to
/Productswill map to theProductscontroller'sIndexaction. - A request to
/Products/Details/5will map to theProductscontroller'sDetailsaction, withidset to5. - A request to
/Orders/Edit/123will map to theOrderscontroller'sEditaction, withidset to123.
Attribute Routing
While convention-based routing is useful, attribute routing offers more control and allows you to define routes directly on controller actions. This is often preferred for creating RESTful APIs or for more complex routing scenarios.
Using the [Route] Attribute
You can apply the [Route] attribute to controllers or individual action methods.
Controller-Level Routing
[Route("api/[controller]")]
public class ProductsController : Controller
{
[HttpGet]
public IActionResult GetAll()
{
// ...
return Ok();
}
[HttpGet("{id}")]
public IActionResult GetById(int id)
{
// ...
return Ok();
}
}
In this example, requests to /api/Products would call GetAll, and requests to /api/Products/1 would call GetById.
Action-Level Routing
public class OrdersController : Controller
{
[HttpGet("myorders")]
public IActionResult ListMyOrders()
{
// ...
return View();
}
[HttpPost("placeorder")]
public IActionResult PlaceNewOrder([FromBody] OrderModel order)
{
// ...
return Ok();
}
}
Requests to /Orders/myorders would call ListMyOrders, and POST requests to /Orders/placeorder would call PlaceNewOrder.
HTTP Verb Constraints
You can specify the HTTP verb directly in attribute routing using attributes like [HttpGet], [HttpPost], [HttpPut], [HttpDelete], etc.
Important: When using attribute routing on a controller, you typically don't need the {controller} and {action} placeholders within the attribute if you're defining them directly on the action. However, you can combine them for more complex scenarios.
Route Parameters and Constraints
Route templates can include parameters (like {id}) and constraints to define what constitutes a valid match. Constraints are applied using colons, e.g., {id:int}.
[Route("users/{userId:guid}")]
public class UsersController : Controller
{
public IActionResult Profile(Guid userId)
{
// ...
return View();
}
}
This route would only match URLs where userId is a valid GUID, like /users/a1b2c3d4-e5f6-7890-1234-567890abcdef.
Common Constraints
int: Matches an integer.guid: Matches a GUID.alpha: Matches only alphabetic characters.regex(pattern): Matches a regular expression pattern.
Order of Route Definition
The order in which routes are defined matters. The routing engine processes routes in the order they are registered. The first route that successfully matches the incoming URL will be used.
Tip: For applications with distinct sections or APIs, consider defining more specific routes (often using attribute routing) before the general default route to ensure correct matching.
Summary
Routing is fundamental to how ASP.NET Core MVC handles incoming requests. Understanding both convention-based and attribute routing, along with route parameters and constraints, is crucial for building well-structured and maintainable web applications.