Как настраивается маршрутизация (Routing) в контроллере ASP.NET Core?

Ответ

В ASP.NET Core маршрутизация настраивается двумя основными способами: атрибутной (рекомендуется для API) и конвенциональной маршрутизацией.

1. Атрибутная маршрутизация (Attribute Routing)

Наиболее гибкий и явный способ. Маршруты задаются с помощью атрибутов [Route], [HttpGet], [HttpPost] и т.д.

[ApiController]
[Route("api/[controller]")] // Базовый маршрут для всего контроллера
public class ProductsController : ControllerBase
{
    // GET api/products/5
    [HttpGet("{id:int}")]
    public IActionResult GetById(int id) { ... }

    // POST api/products
    [HttpPost]
    public IActionResult Create([FromBody] Product product) { ... }

    // GET api/products/category/books
    [HttpGet("category/{categoryName}")]
    public IActionResult GetByCategory(string categoryName) { ... }
}

Ключевые моменты:

  • [controller] и [action] — токены, заменяемые на имя контроллера (без суффикса "Controller") и метода.
  • Можно задавать ограничения для параметров прямо в шаблоне ({id:int}).
  • Позволяет создавать иерархические, RESTful-пути.

2. Конвенциональная маршрутизация (Conventional Routing)

Задается глобально в конфигурации приложения (обычно в Program.cs).

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.MapControllerRoute(
    name: "blog",
    pattern: "blog/{*slug}",
    defaults: new { controller = "Blog", action = "ReadPost" });

Когда использовать:

  • Для приложений с традиционной структурой MVC (страницы, а не API).
  • Когда нужен единый шаблон маршрутов для многих контроллеров.

Best Practice: Для веб-API предпочтительнее атрибутная маршрутизация, так как она делает пути явными и упрощает поддержку.

Ответ 18+ 🔞

Ну слушай, с маршрутизацией в ASP.NET Core вообще-то всё просто, как три копейки. Есть два главных подхода, и они, блядь, как день и ночь.

Первый — это атрибутная маршрутизация. Её все сейчас нахваливают, особенно для API. Суть в том, что ты прямо над своим методом пишешь, по какому адресу его вызывать. Всё явно, всё на виду, никакой магии.

[ApiController]
[Route("api/[controller]")] // Вот тут контроллер будет Products, потому что класс называется ProductsController
public class ProductsController : ControllerBase
{
    // GET api/products/5
    [HttpGet("{id:int}")] // И смотри, id только целочисленный, сразу отсекаем хуйню
    public IActionResult GetById(int id) { ... }

    // POST api/products
    [HttpPost] // Всё, приехали, создаём новый продукт
    public IActionResult Create([FromBody] Product product) { ... }

    // GET api/products/category/books
    [HttpGet("category/{categoryName}")] // А вот так уже иерархию делаем, красиво
    public IActionResult GetByCategory(string categoryName) { ... }
}

Чем хороша? Да всем! Ты сразу видишь, какой путь к какому методу ведёт. Никаких сюрпризов. Хочешь api/products/ultra-mega-super — пожалуйста, пиши атрибут и не парься. Для API — это просто песня, рекомендую.


А второй способ — это конвенциональная маршрутизация, она же традиционная. Это когда ты в одном месте, обычно в Program.cs, прописываешь шаблоны для всех подряд. Типа "все контроллеры будут работать по такому правилу".

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}"); // Классика жанра: controller/action/id

app.MapControllerRoute(
    name: "blog",
    pattern: "blog/{*slug}", // Звёздочка — это "всё, что угодно после blog/"
    defaults: new { controller = "Blog", action = "ReadPost" });

Эта штука удобна, если у тебя приложение в стиле старого доброго MVC, с кучей страниц, где структура Контроллер/Действие/Айдишник всех устраивает. Но, честно говоря, для API это уже немного прошлый век. Мало того что пути неочевидные, так ещё и можно ненароком два метода на один маршрут замапить — потом ищи, где конфликт, волосы на жопе выдергивай.

Так что мой вердикт, если что-то типа API делаешь — бери атрибутную маршрутизацию и не мучайся. Всё прозрачно, всё под контролем, и коллеги тебя потом за код не побьют. А конвенциональную оставь для каких-нибудь легаси-проектов или простых сайтов-визиток, где мозг выключать можно.