Nguon: Microsoft Learn · .NET 8.0

Xử lý request bằng Controllers trong ASP.NET Core MVC

Nguồn: Handle requests with controllers in ASP.NET Core MVC

Bởi Steve SmithScott Addie

Controllers (bộ điều khiển), actions (hành động), và action results (kết quả hành động) là thành phần cơ bản trong cách các nhà phát triển xây dựng ứng dụng bằng ASP.NET Core MVC.

Controller là gì?

Controller được dùng để định nghĩa và nhóm một tập các actions. Một action (hay action method) là phương thức trên controller xử lý các request. Controllers nhóm các actions tương tự lại với nhau. Sự gom nhóm actions này cho phép áp dụng các tập quy tắc chung như routing (định tuyến), caching (lưu đệm), và authorization (phân quyền) một cách tập thể. Các request được ánh xạ đến actions thông qua routing. Controllers được khởi tạo và hủy trên cơ sở mỗi request.

Theo quy ước, các lớp controller:

Controller là lớp có thể khởi tạo, thường là public, trong đó ít nhất một trong các điều kiện sau là đúng:

Lớp controller không được có thuộc tính [NonController] liên kết.

Controllers nên tuân theo Explicit Dependencies Principle (Nguyên tắc phụ thuộc tường minh). Có hai cách tiếp cận để thực hiện nguyên tắc này. Nếu nhiều action trên controller cùng cần một service (dịch vụ), hãy dùng constructor injection (tiêm qua constructor). Nếu service chỉ cần thiết cho một action method duy nhất, hãy dùng Action Injection (tiêm qua action).

Trong mẫu Model-View-Controller, controller chịu trách nhiệm xử lý ban đầu request và khởi tạo model (mô hình). Thông thường, các quyết định nghiệp vụ nên được thực hiện trong model.

Controller nhận kết quả xử lý của model (nếu có) và trả về view thích hợp cùng dữ liệu view liên quan, hoặc kết quả của lời gọi API.

Controller là một abstraction (lớp trừu tượng) ở cấp UI. Trách nhiệm của nó là đảm bảo dữ liệu request hợp lệ và chọn view (hoặc kết quả cho API) nào sẽ được trả về. Trong các ứng dụng được thiết kế tốt, controller không trực tiếp bao gồm logic truy cập dữ liệu hay logic nghiệp vụ. Thay vào đó, controller ủy quyền cho các service xử lý các trách nhiệm này.

Định nghĩa Actions

Các phương thức public trên controller, ngoại trừ những phương thức có thuộc tính [NonAction], đều là actions. Các tham số trên actions được bind (ràng buộc) từ dữ liệu request và được validate (xác thực) bằng model binding (ràng buộc mô hình). Validation mô hình xảy ra cho mọi thứ được model-bind. Giá trị thuộc tính ModelState.IsValid cho biết model binding và validation đã thành công hay chưa.

Action methods nên chứa logic để ánh xạ request đến một mối quan tâm nghiệp vụ. Các mối quan tâm nghiệp vụ thường được đại diện dưới dạng services mà controller truy cập thông qua dependency injection (tiêm phụ thuộc). Các action sau đó ánh xạ kết quả của hành động nghiệp vụ đến trạng thái ứng dụng.

Actions có thể trả về bất kỳ thứ gì, nhưng thường trả về instance IActionResult (hoặc Task<IActionResult> cho các phương thức async) để tạo response. Action method chịu trách nhiệm chọn loại response nào. Action result thực hiện việc phản hồi.

Các phương thức Helper của Controller

Controllers thường kế thừa từ Controller, dù không bắt buộc. Kế thừa từ Controller cung cấp quyền truy cập ba danh mục phương thức helper:

1. Phương thức tạo response body rỗng

Không có HTTP response header Content-Type vì response body không có nội dung để mô tả.

Có hai kiểu result trong danh mục này: RedirectHTTP Status Code.

Kiểu này trả về HTTP status code. Một số phương thức helper của kiểu này là BadRequest, NotFound, và Ok. Ví dụ return BadRequest(); tạo ra status code 400 khi được thực thi. Khi các phương thức như BadRequest, NotFound, và Ok bị overload (nạp chồng), chúng không còn là HTTP Status Code responder nữa vì content negotiation (thỏa thuận nội dung) đang diễn ra.

Kiểu này trả về redirect đến một action hoặc đích (dùng Redirect, LocalRedirect, RedirectToAction, hoặc RedirectToRoute). Ví dụ return RedirectToAction("Complete", new {id = 123}); redirect đến Complete, truyền đối tượng ẩn danh.

Kiểu Redirect khác kiểu HTTP Status Code chủ yếu ở việc thêm HTTP response header Location.

2. Phương thức tạo response body không rỗng với content type được định sẵn

Hầu hết phương thức helper trong danh mục này có thuộc tính ContentType, cho phép thiết lập response header Content-Type để mô tả response body.

Có hai kiểu result trong danh mục này: ViewFormatted Response.

Kiểu này trả về view dùng model để render HTML. Ví dụ return View(customer); truyền model vào view để data-binding.

Kiểu này trả về JSON hoặc định dạng trao đổi dữ liệu tương tự để biểu diễn đối tượng theo cách cụ thể. Ví dụ return Json(customer); serialize (tuần tự hóa) đối tượng sang định dạng JSON.

Các phương thức phổ biến khác của kiểu này bao gồm FilePhysicalFile. Ví dụ return PhysicalFile(customerFilePath, "text/xml"); trả về PhysicalFileResult.

3. Phương thức tạo response body không rỗng với content type được thỏa thuận với client

Danh mục này còn được gọi là Content Negotiation (Thỏa thuận nội dung). Content negotiation áp dụng khi action trả về kiểu ObjectResult hoặc thứ gì đó khác với implementation IActionResult. Action trả về implementation không phải IActionResult (ví dụ object) cũng trả về Formatted Response.

Một số phương thức helper của kiểu này bao gồm BadRequest, CreatedAtRoute, và Ok. Ví dụ return BadRequest(modelState);, return CreatedAtRoute("routename", values, newobject);, và return Ok(value);. Lưu ý BadRequestOk chỉ thực hiện content negotiation khi được truyền giá trị; không có giá trị, chúng là kiểu HTTP Status Code. Phương thức CreatedAtRoute luôn thực hiện content negotiation vì tất cả overload của nó đều yêu cầu truyền giá trị.

Cross-Cutting Concerns (Mối quan tâm xuyên suốt)

Các ứng dụng thường chia sẻ các phần của workflow. Ví dụ, ứng dụng yêu cầu authentication (xác thực) để truy cập giỏ hàng, hoặc ứng dụng cache (lưu đệm) dữ liệu trên một số trang. Để thực thi logic trước hoặc sau action method, hãy dùng filter (bộ lọc). Dùng Filters (Bộ lọc) cho các cross-cutting concerns có thể giảm trùng lặp.

Hầu hết filter attributes (thuộc tính bộ lọc), chẳng hạn [Authorize], có thể được áp dụng ở cấp controller hoặc action tùy thuộc vào mức độ chi tiết mong muốn.

Xử lý lỗi và response caching thường là các cross-cutting concerns:

Nhiều cross-cutting concerns có thể được xử lý bằng filters hoặc middleware (phần mềm trung gian) tùy chỉnh.