VieTopik
Tiếng HànTiếng AnhIT
  • Góc học tập
Tải app
  • Thư viện
  • Luyện thi
  • Cẩm nang
  • Góc học tập
ASP.NET Core Web APIXây API CRUD
Bài 7/19
5 phút

Validation

Nội dung bài · 5 mục
  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt

Client gửi sản phẩm tên rỗng, giá âm. Nếu API cứ thế lưu vào thì dữ liệu hỏng từ đầu. Validation chặn dữ liệu sai ngay ở cửa, trước khi action kịp chạy.

Khái niệm

✅ Validation: bước kiểm tra dữ liệu client gửi lên có hợp lệ không trước khi xử lý.

🔖 Data annotation: attribute gắn lên property của DTO để khai báo quy tắc, ví dụ [Required], [Range].

Attribute Quy tắc
[Required] bắt buộc có, chuỗi không được rỗng
[StringLength(100)] chuỗi tối đa 100 ký tự
[Range(1, 100000000)] số nằm trong khoảng
[EmailAddress] đúng định dạng email

Ví dụ

using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/products")]
public class ProductsController : ControllerBase
{
    [HttpPost]
    public ActionResult<string> Create(
        CreateProductRequest request)
    {
        return Ok($"Đã tạo {request.Name}");
    }
}

public class CreateProductRequest
{
    [Required(ErrorMessage = "Tên không được trống")]
    [StringLength(100)]
    public string Name { get; set; } = "";

    [Range(1, 100000000,
        ErrorMessage = "Giá phải từ 1 đến 100 triệu")]
    public decimal Price { get; set; }
}
  • Quy tắc nằm ngay trên DTO, cần using System.ComponentModel.DataAnnotations.
  • [ApiController] tự kiểm tra DTO trước khi gọi action. Sai quy tắc thì trả 400 kèm danh sách lỗi, action không chạy.
  • ErrorMessage đặt câu báo lỗi riêng thay cho câu mặc định bằng tiếng Anh.
  • Validation chặn ở API để trả 400 dễ hiểu. NOT NULL, CHECK ở bài CREATE TABLE của khoá SQL vẫn là lớp chặn cuối trong database.
Đúng Sai POST /api/products DTO đúng quy tắc? Action Create chạy, trả 200 Trả 400 kèm danh sách lỗi
Dữ liệu sai bị chặn trước khi vào action

Thử ngay

Chạy server. Tạo file product.json với dữ liệu sai:

{ "name": "", "price": -5 }

Rồi gửi:

curl -i -X POST http://localhost:5000/api/products -H "Content-Type: application/json" -d @product.json

Đoán trước khi chạy: action có chạy tới dòng return Ok(...) không, và response báo mấy lỗi?

Xem kết quả
HTTP/1.1 400 Bad Request
Content-Type: application/problem+json

{
  "title": "One or more validation errors occurred.",
  "status": 400,
  "errors": {
    "Name": ["T\u00EAn kh\u00F4ng \u0111\u01B0\u1EE3c tr\u1ED1ng"],
    "Price": ["Gi\u00E1 ph\u1EA3i t\u1EEB 1 \u0111\u1EBFn 100 tri\u1EC7u"]
  }
}

Body trên đã rút gọn, bản thật có thêm type và traceId.

Action không chạy. [ApiController] chặn từ trước và trả 400 kèm hai lỗi, mỗi lỗi gắn với tên property. Chữ có dấu bị mã hoá dạng \u00EA khi xem bằng curl, còn client đọc JSON sẽ hiện lại đúng "Tên không được trống".

Lỗi hay gặp

Tự kiểm tra bằng if trong từng action. Quy tắc bị chép rải rác, sửa một chỗ dễ quên chỗ khác.

// SAI — quy tắc nằm trong action, phải chép lại ở PUT
using Microsoft.AspNetCore.Mvc;

public class ItemsController : ControllerBase
{
    [HttpPost]
    public ActionResult<string> Create(string name)
    {
        if (string.IsNullOrWhiteSpace(name))
        {
            return BadRequest("Tên không được trống");
        }
        return Ok(name);
    }
}

Đặt quy tắc thành attribute trên DTO thì mọi action dùng DTO đó đều được kiểm tra.

// ĐÚNG — quy tắc nằm trên DTO
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/items")]
public class ItemsController : ControllerBase
{
    [HttpPost]
    public ActionResult<string> Create(
        CreateItemRequest request)
    {
        return Ok(request.Name);
    }
}

public class CreateItemRequest
{
    [Required(ErrorMessage = "Tên không được trống")]
    public string Name { get; set; } = "";
}

Quên [ApiController]. Không có nó thì dữ liệu sai vẫn lọt vào action, vì không còn bước nào tự trả 400.

Tóm tắt

  • Validation chặn dữ liệu sai trước khi action chạy.
  • Khai báo quy tắc bằng attribute trên DTO: [Required], [Range], [StringLength].
  • [ApiController] tự trả 400 kèm danh sách lỗi theo từng property.
  • Dùng ErrorMessage để có câu báo lỗi dễ hiểu cho người dùng.

Tự kiểm tra

0/3 câu
Câu 1

DTO có [Range(1, 10)] public int Quantity. Client gửi quantity = 0. Chuyện gì xảy ra?

Câu 2

Muốn email của khách hàng vừa bắt buộc vừa đúng định dạng. Gắn attribute nào?

Câu 3

Quy tắc validation nên đặt ở đâu?

DTOCRUD hoàn chỉnh

Nội dung bài

  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt