Какие способы настройки маршрутизации в ASP.NET Core приложении ты знаешь?

«Какие способы настройки маршрутизации в ASP.NET Core приложении ты знаешь?» — вопрос из категории ASP.NET Core, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Маршрутизация в 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}) для параметров маршрута, где это возможно.