Nguon: Microsoft Learn · .NET 8.0

Phần 9: Thêm Validation vào ứng dụng ASP.NET Core MVC

Nguồn: Part 9, add validation to an ASP.NET Core MVC app

Nguyên tắc DRY

Một trong những nguyên tắc thiết kế cốt lõi của MVC là DRY (Don't Repeat Yourself - Không lặp lại bản thân). ASP.NET Core MVC khuyến khích bạn chỉ định chức năng hoặc hành vi một lần và sau đó phản ánh ở khắp nơi trong ứng dụng. Điều này làm giảm lượng code bạn cần viết và làm cho code ít bị lỗi hơn, dễ kiểm tra và dễ bảo trì hơn.

Hỗ trợ validation (xác thực) được cung cấp bởi MVC và Entity Framework Core là một ví dụ điển hình về nguyên tắc DRY. Bạn có thể chỉ định các quy tắc validation một cách khai báo ở một nơi (trong model class) và các quy tắc được thực thi ở khắp nơi trong ứng dụng.

Thêm validation rules vào Movie Model

Mở file Models/Movie.cs. DataAnnotations (chú thích dữ liệu) cung cấp một tập hợp các thuộc tính validation được tích hợp sẵn có thể áp dụng theo cách khai báo cho bất kỳ class hoặc thuộc tính nào. DataAnnotations cũng chứa các thuộc tính định dạng như DataType giúp định dạng và không cung cấp bất kỳ validation nào.

Cập nhật class Movie để tận dụng các thuộc tính validation tích hợp sẵn Required, StringLength, RegularExpression, và Range.

csharp
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MvcMovie.Models;

public class Movie
{
    public int Id { get; set; }

    [StringLength(60, MinimumLength = 3)]
    [Required]
    public string? Title { get; set; }

    [Display(Name = "Release Date")]
    [DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    [Range(1, 100)]
    [DataType(DataType.Currency)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }    

    [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$")]
    [Required]
    [StringLength(30)]
    public string? Genre { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
    [StringLength(5)]
    [Required]
    public string? Rating { get; set; }
}

Các thuộc tính validation chỉ định hành vi bạn muốn thực thi trên các thuộc tính model mà chúng được áp dụng:

Việc tự động thực thi các quy tắc validation bởi ASP.NET Core giúp ứng dụng của bạn mạnh hơn. Nó cũng đảm bảo rằng bạn không thể quên validate thứ gì đó và vô tình để dữ liệu xấu vào cơ sở dữ liệu.

UI lỗi Validation

Chạy ứng dụng và điều hướng đến Movies controller.

Nhấp vào link Create New để thêm một bộ phim mới. Điền vào form với một số giá trị không hợp lệ. Ngay khi jQuery client-side validation (xác thực phía client) phát hiện lỗi, nó sẽ hiển thị thông báo lỗi.

Bạn có thể không thể nhập dấu thập phân trong trường Price. Để hỗ trợ jQuery validation cho các ngôn ngữ không phải tiếng Anh sử dụng dấu phẩy (",") cho dấu thập phân và các định dạng ngày không phải US, bạn phải thực hiện các bước để quốc tế hóa ứng dụng của mình.

Lưu ý cách form tự động hiển thị thông báo lỗi validation phù hợp trong mỗi trường chứa giá trị không hợp lệ. Các lỗi được thực thi cả phía client (sử dụng JavaScript và jQuery) và phía server (trong trường hợp người dùng bị tắt JavaScript).

Một lợi ích đáng kể là bạn không cần thay đổi một dòng code nào trong class MoviesController hoặc trong view Create.cshtml để bật UI validation này. Controller và view bạn tạo trước đó trong hướng dẫn này đã tự động chọn các quy tắc validation mà bạn đã chỉ định bằng cách sử dụng các thuộc tính validation trên các thuộc tính của class model Movie. Kiểm tra validation bằng cách sử dụng action method Edit và áp dụng validation tương tự.

Dữ liệu form không được gửi đến server cho đến khi không còn lỗi validation phía client.

Validation hoạt động như thế nào

Bạn có thể tự hỏi làm thế nào UI validation được tạo ra mà không cần cập nhật bất kỳ code nào trong controller hoặc view. Code sau hiển thị hai method Create.

csharp
// GET: Movies/Create
public IActionResult Create()
{
    return View();
}

// POST: Movies/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
    if (ModelState.IsValid)
    {
        _context.Add(movie);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    return View(movie);
}

Method action Create đầu tiên (HTTP GET) hiển thị form Create ban đầu. Phiên bản thứ hai ([HttpPost]) xử lý form post. Method [HttpPost] thứ hai gọi ModelState.IsValid để kiểm tra xem phim có bất kỳ lỗi validation nào không. Gọi method này đánh giá bất kỳ thuộc tính validation nào đã được áp dụng cho đối tượng. Nếu đối tượng có lỗi validation, method Create hiển thị lại form. Nếu không có lỗi, method sẽ lưu phim mới vào cơ sở dữ liệu.

Trong ví dụ phim, form không được post lên server khi có lỗi validation được phát hiện phía client; method [HttpPost] thứ hai không bao giờ được gọi khi có lỗi validation phía client. Nếu bạn tắt JavaScript trong trình duyệt, validation phía client bị tắt và bạn có thể kiểm tra method HTTP POST Create với ModelState.IsValid phát hiện bất kỳ lỗi validation nào.

Thuộc tính DataType

Mở file Movie.cs và kiểm tra class Movie. Namespace System.ComponentModel.DataAnnotations cung cấp các thuộc tính định dạng ngoài tập hợp các thuộc tính validation tích hợp sẵn. Chúng ta đã áp dụng giá trị enum DataType cho ngày phát hành và các trường giá. Các thuộc tính DataType chỉ cung cấp gợi ý cho view engine (công cụ hiển thị) để định dạng dữ liệu (và cung cấp các thuộc tính như <a> cho URL và <a href="mailto:EmailAddress.com"> cho email).

Thuộc tính DataType được sử dụng để chỉ định một kiểu dữ liệu cụ thể hơn kiểu cơ sở dữ liệu, chúng không phải là thuộc tính validation. Trong trường hợp này, chúng ta chỉ muốn theo dõi ngày, không phải thời gian. Enum DataType cung cấp cho nhiều kiểu dữ liệu, chẳng hạn như Date, Time, PhoneNumber, Currency, EmailAddress và nhiều hơn nữa.

Thêm Migrations cho các quy tắc validation

Các thuộc tính DataAnnotations validation xác định các thay đổi bạn muốn thực hiện đối với cơ sở dữ liệu schema. Ví dụ:

Visual Studio

powershell
Add-Migration New_DataAnnotations
Update-Database

Visual Studio Code (.NET CLI)

bash
dotnet ef migrations add New_DataAnnotations
dotnet ef database update

Lưu ý cho SQLite: Do các giới hạn của SQLite, không phải tất cả các thay đổi schema đều được hỗ trợ. Xóa thư mục Migrations và cơ sở dữ liệu, sau đó chạy lại các lệnh migration nếu cần.

Sau khi chạy Update-Database, mở file migration mới được tạo và lưu ý các ràng buộc mới được áp dụng cho cơ sở dữ liệu. Các thuộc tính validation trong model class được ánh xạ trực tiếp sang các ràng buộc cơ sở dữ liệu.