Ответ
Маршрутизация в ASP.NET Core настраивается несколькими способами, от конвенциональных до полностью кастомных.
1. Конвенциональная маршрутизация (Conventional Routing)
Настраивается глобально в Program.cs или Startup.Configure. Это стиль, знакомый по ASP.NET MVC.
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
// Дополнительные маршруты
app.MapControllerRoute(
name: "blog",
pattern: "blog/{*slug}",
defaults: new { controller = "Blog", action = "ReadPost" });
2. Атрибутная маршрутизация (Attribute Routing) Наиболее гибкий и предпочтительный способ. Маршруты задаются напрямую над контроллерами и действиями.
[Route("api/[controller]")] // Базовый маршрут: /api/products
[ApiController]
public class ProductsController : ControllerBase
{
[HttpGet] // GET /api/products
public IActionResult GetAll() { ... }
[HttpGet("{id:int}")] // GET /api/products/5
public IActionResult GetById(int id) { ... }
[HttpPost("special")] // POST /api/products/special
public IActionResult PostSpecial([FromBody] Product product) { ... }
}
3. Маршрутизация в минимальных API (Minimal APIs)
Использует методы расширения MapGet, MapPost и т.д.
app.MapGet("/products", () => "Список продуктов");
app.MapGet("/products/{id:int}", (int id) => $"Продукт {id}");
app.MapPost("/products", (Product product) => Results.Created($"/products/{product.Id}", product));
4. Динамическая/кастомная маршрутизация
Можно создать собственный IRouteConstraint для валидации параметров или реализовать DynamicRouteValueTransformer для динамического преобразования маршрутов на лету (например, для мультитенантности или CMS).
// Пользовательское ограничение
public class CustomConstraint : IRouteConstraint { ... }
// Использование в атрибуте
[HttpGet("{id:customConstraint}")]
public IActionResult Get(string id) { ... }
5. Маршрутизация по областям (Areas) Организует контроллеры и представления в отдельные группы для больших приложений.
[Area("Admin")]
[Route("Admin/[controller]/[action]")]
public class UsersController : Controller { ... }
Ключевые принципы:
- Используйте атрибутную маршрутизацию для API и сложных схем.
- Порядок регистрации маршрутов важен — более специфичные должны регистрироваться раньше общих.
- Всегда добавляйте ограничения типов (
{id:int}) для параметров маршрута, где это возможно.