Ответ
В 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 делаешь — бери атрибутную маршрутизацию и не мучайся. Всё прозрачно, всё под контролем, и коллеги тебя потом за код не побьют. А конвенциональную оставь для каких-нибудь легаси-проектов или простых сайтов-визиток, где мозг выключать можно.