Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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

AspectConventional RoutingAttribute Routing
DefinitionTập trung trong configTrực tiếp trên method
FlexibilityLinh hoạt với patternsChi tiết, rõ ràng
RESTfulKhó tạo RESTfulDễ dàng
ConventionTheo quy ước đặt tênTùy chỉnh
Use caseMVC với ViewsWeb 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

ConstraintExampleDescription
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:

  1. Static segments (e.g., api/products)
  2. Route parameters có constraints
  3. Route parameters không constraints
  4. Catch-all parameters