Routing
Conventional Routing vs Attribute Routing
Conventional Routing (MVC)
Định nghĩa routes tập trung trong Program.cs hoặc Startup.cs:
// Program.cs
app.UseRouting();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapControllerRoute(
name: "blog",
pattern: "blog/{*slug}",
defaults: new { controller = "Blog", action = "Post" });
// Hoặc routes phân cấp
app.MapControllerRoute(
name: "products",
pattern: "products/{category}/{action}",
defaults: new { controller = "Products" });
Controller:
public class ProductsController : Controller
{
public IActionResult Index()
{
return View();
}
public IActionResult Details(int id)
{
return View(id);
}
}
Attribute Routing (Web API)
Định nghĩa routes trực tiếp trên controller/action:
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
[HttpGet]
public IActionResult GetAll()
{
return Ok();
}
[HttpGet("{id:int}")]
public IActionResult GetById(int id)
{
return Ok(id);
}
[HttpPost]
public IActionResult Create([FromBody] Product product)
{
return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);
}
[HttpPut("{id:int}")]
public IActionResult Update(int id, [FromBody] Product product)
{
return NoContent();
}
[HttpDelete("{id:int}")]
public IActionResult Delete(int id)
{
return NoContent();
}
}
So sánh
| Aspect | Conventional Routing | Attribute Routing |
|---|---|---|
| Definition | Tập trung trong config | Trực tiếp trên method |
| Flexibility | Linh hoạt với patterns | Chi tiết, rõ ràng |
| RESTful | Khó tạo RESTful | Dễ dàng |
| Convention | Theo quy ước đặt tên | Tùy chỉnh |
| Use case | MVC với Views | Web API |
Route Templates
Basic Templates
[HttpGet("/products")] // Exact: /products
[HttpGet("products/{id}")] // Parameter: /products/1
[HttpGet("products/{id:int}")] // Typed: /products/1 (chấp nhận số)
[HttpGet("products/{name:alpha}")] // Constraint: chỉ chữ cái
[HttpGet("products/{*slug}")] // Catch-all: /products/a/b/c
Route Constraints
| Constraint | Example | Description |
|---|---|---|
int | {id:int} | Chỉ số nguyên |
bool | {active:bool} | Chỉ true/false |
datetime | {date:datetime} | Giá trị datetime |
guid | {id:guid} | GUID |
length | {name:length(3,10)} | Độ dài cụ thể |
range | {age:range(18,100)} | Khoảng giá trị |
regex | {code:regex(^\\d{3}$)} | Regex pattern |
Optional Parameters
[HttpGet("products/{category?}")]
public IActionResult GetByCategory(string? category)
{
// category có thể null hoặc có giá trị
}
Default Values
[HttpGet("products")]
public IActionResult GetAll([FromQuery] int page = 1, [FromQuery] int pageSize = 10)
{
// Default values
}
Route Ordering
Explicit Order với [Route] attribute
[ApiController]
[Route("api/[controller]")]
public class ItemsController : ControllerBase
{
// Đặt specific routes trước generic routes
[HttpGet("best-selling")] // ✅ Matches /api/items/best-selling
public IActionResult GetBestSelling()
{
return Ok();
}
[HttpGet("{id}")] // ❌ Sẽ không bao giờ được gọi nếu đặt sau
public IActionResult GetById(int id)
{
return Ok(id);
}
}
Route Precedence
ASP.NET Core ưu tiên:
- Static segments (e.g.,
api/products) - Route parameters có constraints
- Route parameters không constraints
- Catch-all parameters