Introduction to MVC Routing
Routing is a core concept in ASP.NET Core MVC. It determines how incoming browser requests are mapped to the correct action method in your controllers. By defining routes, you control the structure of the URLs your application exposes, making them user-friendly and SEO-friendly.
ASP.NET Core MVC uses a convention-based routing system that's highly flexible. You define a route template that includes placeholders for segments like controller, action, and optional parameters.
Default Routing Convention
By default, ASP.NET Core MVC applications are configured to use a "Conventional Routing" approach. The standard route template is often defined as follows:
/{controller}/{action}/{id?}
Let's break this down:
{controller}
: This placeholder represents the name of the controller. For example, a request to/Home/Index
would map to theIndex
action of theHomeController
.{action}
: This placeholder represents the name of the action method within the controller.{id?}
: This is an optional parameter. The question mark (?
) indicates that this segment is optional. It's commonly used to pass an identifier, such as a primary key for a resource.
If you don't specify an action, the default action (usually Index
) will be invoked.
If you don't specify a controller, the default controller (usually Home
) will be used.
Configuring Routes in Startup.cs
(or Program.cs
)
The routing configuration is typically done in the Configure
method of your Startup.cs
file (or directly in Program.cs
for newer .NET versions using minimal APIs). This is where you register the routing middleware.
Using UseRouting()
and UseEndpoints()
In modern ASP.NET Core applications, routing is handled by two key middleware components:
UseRouting()
: This middleware adds the routing services to the request pipeline and discovers endpoints.UseEndpoints()
: This middleware runs the selected endpoint, which typically involves invoking an MVC controller action.
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting(); // Enable endpoint routing
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
// Map the default controller/action/id route
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
app.Run();
Startup.cs
class, the configuration would look similar within the Configure
method:
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
Custom Route Templates
You're not limited to the default routing pattern. You can define custom routes to create more specific or user-friendly URLs. This is particularly useful for creating cleaner URLs for product pages, blog posts, or specific feature endpoints.
Example: Product Route
Let's say you want URLs like /products/details/my-awesome-product-slug
. You can define a custom route like this:
endpoints.MapControllerRoute(
name: "productdetails",
pattern: "products/details/{slug?}", // Custom pattern with a slug parameter
defaults: new { controller = "Products", action = "Details" });
In this example:
name: "productdetails"
: A unique name for this route.pattern: "products/details/{slug?}"
: The URL pattern. It starts with a fixed path "products/details" and includes an optionalslug
parameter.defaults: new { controller = "Products", action = "Details" }
: Specifies the default controller and action if these are not provided in the URL.
Attribute Routing
Attribute routing offers an even more declarative way to define routes directly on your controller actions using attributes. This approach embeds routing information directly within your code, making it easy to see which URL maps to which action.
Example: Attribute Routing
To use attribute routing, you need to ensure MapAttributeRoutes()
is called in your UseEndpoints
configuration.
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers(); // This maps attribute-routed controllers
// You can still have conventional routes alongside attribute routes
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
Now, decorate your controller actions with the [Route]
attribute:
using Microsoft.AspNetCore.Mvc;
namespace MyWebApp.Controllers
{
public class CatalogController : Controller
{
[Route("catalog")] // Maps to CatalogController.Index()
[Route("catalog/all")] // Also maps to CatalogController.Index()
public IActionResult Index()
{
return View();
}
[Route("catalog/items/{category}")] // Maps to CatalogController.Items(string category)
public IActionResult Items(string category)
{
ViewBag.Category = category;
return View();
}
[HttpGet("products/{id:int}")] // Maps to CatalogController.ProductDetail(int id) with GET method
public IActionResult ProductDetail(int id)
{
ViewBag.ProductId = id;
return View();
}
}
}
Notice the use of route constraints (:int
) and HTTP method constraints ([HttpGet]
) for even more precise routing.
Route Constraints
Route constraints allow you to specify rules for the values of route parameters. This ensures that only requests matching the constraint will be routed to the specified action.
int
: Parameter must be an integer.alpha
: Parameter must contain only alphabetic characters.guid
: Parameter must be a GUID.datetime
: Parameter must be a valid date and time.{parameter:regex(your_pattern)}
: Custom regular expression.