ASP.NET Core: Định tuyến trong ASP.NET Web API
Bài viết này mô tả cách ASP.NET Web API định tuyến (routing) các yêu cầu HTTP đến controller.
Ghi chú
Nếu bạn quen thuộc với ASP.NET MVC, việc định tuyến Web API rất giống với định tuyến MVC. Sự khác biệt chính là Web API sử dụng verb HTTP chứ không phải đường dẫn URI để chọn action. Bạn cũng có thể sử dụng định tuyến kiểu MVC trong Web API. Bài viết này không có bất kỳ kiến thức nào về ASP.NET MVC.
Bảng định tuyến
Trong ASP.NET Web API, controller là lớp xử lý các yêu cầu HTTP. Các phương thức public của controller được gọi là các phương thức action hoặc đơn giản là các action. Khi framework Web API nhận được yêu cầu, nó sẽ chuyển yêu cầu đó đến một action.
Để xác định action nào cần thực hiện, framework sử dụng bảng định tuyến. Mẫu dự án Visual Studio cho Web API tạo route mặc định:
routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Route này được xác định trong file WebApiConfig.cs, được đặt trong thư mục App_Start:
Để biết thêm thông tin về lớp WebApiConfig, hãy xem Định cấu hình ASP.NET Web API.
Nếu bạn tự lưu trữ Web API, bạn phải đặt bảng định tuyến trực tiếp trên đối tượng HttpSelfHostConfiguration. Để biết thêm thông tin, hãy xem Tự lưu trữ WEB API.
Mỗi mục trong bảng định tuyến chứa một mẫu route. Mẫu route mặc định cho API Web là "api/{controller}/{id}". Trong mẫu này, "api" là một đoạn đường dẫn bằng chữ và {controller} và {id} là các biến giữ chỗ.
Khi framework WEB API nhận được yêu cầu HTTP, nó sẽ cố gắng khớp URI với một trong các mẫu route trong bảng định tuyến. Nếu không có route nào khớp, máy khách sẽ nhận được lỗi 404. Ví dụ: các URI sau khớp với route mặc định:
- /api/contacts
- /api/contacts/1
- /api/products/gizmo1
Tuy nhiên, URI sau không khớp vì nó thiếu phân đoạn "api":
- /contacts/1
Ghi chú
Lý do sử dụng "api" trong route là để tránh xung đột với định tuyến ASP.NET MVC. Bằng cách đó, bạn có thể đưa "/contacts" đi tới controller MVC và "/api/contacts" đi tới controller WEB API. Tất nhiên, nếu không thích quy ước này, bạn có thể thay đổi bảng lộ trình mặc định.
Khi tìm thấy route phù hợp, WEB API sẽ chọn controller và action:
- Để tìm controller, WEB API thêm "Controller" vào giá trị của biến {controller}.
- Để tìm action, WEB API xem xét verb HTTP, sau đó tìm kiếm action có tên bắt đầu bằng tên verb HTTP đó. Ví dụ: với yêu cầu GET, thì WEB API sẽ tìm kiếm một action có tiền tố "Get", chẳng hạn như "Getcontact" hoặc "GetAllcontacts". Quy ước này chỉ áp dụng cho các verb GET, POST, PUT, DELETE, HEAD, OPTIONS và PATCH. Bạn có thể kích hoạt các verb HTTP khác bằng cách sử dụng các attribute trên controller của mình. Chúng ta sẽ thấy một ví dụ về điều đó sau.
- Các biến giữ chỗ khác trong mẫu route, chẳng hạn như {id}, được ánh xạ tới các tham số action.
Hãy xem một ví dụ. Giả sử bạn định nghĩa controller sau:
public class ProductsController : ApiController
{
public IEnumerable<Product> GetAllProducts() { }
public Product GetProductById(int id) { }
public HttpResponseMessage DeleteProduct(int id){ }
}
Dưới đây là một số yêu cầu HTTP có thể có, cùng với action được gọi cho mỗi yêu cầu:
| Verb HTTP | Đường dẫn URI | Action | Tham số |
|---|---|---|---|
| GET | api/products | GetAllProducts | (không có) |
| GET | api/products/4 | GetProductById | 4 |
| DELETE | api/products/4 | DeleteProduct | 4 |
| POST | api/products | (không khớp) |
Lưu ý rằng phân đoạn {id} của URI, nếu có, sẽ được ánh xạ tới tham số id của action. Trong ví dụ trên, controller định nghĩa hai phương thức GET, một phương thức có tham số id và một phương thức không có tham số.
Ngoài ra, hãy lưu ý rằng yêu cầu POST sẽ không thành công vì controller không định nghĩa phương thức "Post...".
Các biến thể định tuyến
Phần trên đã mô tả cơ chế định tuyến cơ bản cho ASP.NET Web API. Phần này sẽ mô tả một số biến thể định tuyến.
Verb HTTP
Thay vì sử dụng quy ước đặt tên cho verb HTTP, bạn có thể chỉ định rõ ràng verb HTTP cho một action bằng cách trang bị cho phương thức action bằng một trong các attribute sau:
[HttpGet][HttpPut][HttpPost][HttpDelete][HttpHead][HttpOptions][HttpPatch]
Trong ví dụ sau, phương thức FindProduct được ánh xạ tới các yêu cầu GET:
public class ProductsController : ApiController
{
[HttpGet]
public Product FindProduct(id) {}
}
Để cho phép nhiều verb HTTP cho một action hoặc cho phép các verb HTTP không phải GET, PUT, POST, DELETE, HEAD, OPTIONS và PATCH, hãy sử dụng attribute [AcceptVerbs], bên trong mang danh sách các verb HTTP.
public class ProductsController : ApiController
{
[AcceptVerbs("GET", "HEAD")]
public Product FindProduct(id) { }
// WebDAV method
[AcceptVerbs("MKCOL")]
public void MakeCollection() { }
}
Định tuyến theo tên action
Với mẫu định tuyến mặc định, Web API sử dụng verb HTTP để chọn action. Tuy nhiên, bạn cũng có thể tạo lộ trình có tên action trong URI:
routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Trong mẫu route trên, tham số {action} đặt tên cho phương thức action trên controller. Với kiểu định tuyến này, hãy sử dụng các attribute để chỉ định các verb HTTP được phép. Ví dụ: giả sử controller của bạn có phương thức sau:
public class ProductsController : ApiController
{
[HttpGet]
public string Details(int id);
}
Trong trường hợp này, yêu cầu GET cho "api/products/details/1" sẽ ánh xạ tới phương thức Details. Kiểu định tuyến này tương tự như ASP.NET MVC và có thể phù hợp với API kiểu RPC.
Bạn có thể ghi đè tên action bằng cách sử dụng attribute [ActionName]. Trong ví dụ sau, có hai action ánh xạ tới "api/products/thumbnail/id. Một action hỗ trợ GET và action còn lại hỗ trợ POST:
public class ProductsController : ApiController
{
[HttpGet]
[ActionName("Thumbnail")]
public HttpResponseMessage GetThumbnailImage(int id);
[HttpPost]
[ActionName("Thumbnail")]
public void AddThumbnailImage(int id);
}
NonAction
Để ngăn một phương thức được gọi dưới dạng hành động, hãy sử dụng attribute [NonAction]. Điều này báo hiệu cho framework rằng phương thức này không phải là một action, ngay cả khi nó phù hợp với các quy tắc định tuyến.
// Not an action method.
[NonAction]
public string GetPrivateData() { ... }
Đọc thêm
Chủ đề này cung cấp một cái nhìn cấp cao về định tuyến. Để biết thêm chi tiết, hãy xem phần Định tuyến và Lựa chọn action, mô tả chính xác cách framework khớp URI với một route, chọn controller rồi chọn action để gọi.