Hợp lệ dữ liệu người dùng

Một trong những nội dung quan trọng nhất khi viết ứng dụng ASP.NET Core MVC là hợp lệ dữ liệu người dùng và chúng ta phải thực hiện điều này theo nguyên tắc DRY (Don’t Repeat Yourself). MVC và EF Core Code First hỗ trợ hợp lệ dữ liệu theo nguyên tắc DRY, có nghĩa là, chúng ta sẽ khai báo các luật hợp lệ dữ liệu một lần và sử dụng ở nhiều nơi trong chương trình.

Thêm các luật hợp lệ (Validation rules) đến lớp Book

Như đã từng đề cập, việc hợp lệ dữ liệu người dùng sẽ thực hiện qua hai mức người dùng (client) và máy chủ (server). Tại mức người dùng hay trình duyệt web, hợp lệ dữ liệu diễn ra tự động nhờ chương trình JavaScript. Ví dụ thực thi ứng dụng và mở form Create bằng cách nhấn chuột vào liên kết Create New, sau đó nhập vài kí tự vào trường Price sẽ xuất hiện thông điệp lỗi:

Bây giờ giả sử chúng ta tắt trình JavaScript trên trình duyệt (bài viết này đang sử dụng Chrome vào More tools > Developer tools, nhấn tổ hợp phím Ctr + Shift + P sau đó gõ chữ javascript vào mục Run

chọn Disable JavaScript) và khởi động lại trang Create sẽ thấy xuất hiện dấu hiệu JavaScript đã bị tắt:

Nhập lại vài từ vào trường Price sẽ không xuất hiện bất cứ thông điệp nào. Quá trình hợp lệ dữ liệu không diễn ra tại mức người dùng do chúng ta đã tắt JavaScript nhưng dữ liệu này sẽ được hợp lệ tại mức máy chủ, cụ thể, nếu chúng ta nhấn nút Create sẽ xuất hiện thông báo lỗi:

Giao diện sẽ phát sinh các thông báo khi dữ liệu người dùng không hợp lệ mà không cần cập nhật thêm bất cứ đoạn mã nào đến controller hay view. Nguyên nhân là do phương thức ModelState.IsValid trong phương thức Create:

[HttpPost]

[ValidateAntiForgeryToken]

public async Task<IActionResult> Create([Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Book book)

        {

            if (ModelState.IsValid)

            {

                _context.Add(book);

                await _context.SaveChangesAsync();

                return RedirectToAction(nameof(Index));

            }

            return View(book);

        }

Namespace DataAnnotations cung cấp một tập các thuộc tính hỗ trợ hợp lệ dữ liệu đến một lớp hay các thuộc tính của lớp. Trong các bài trước chúng ta đã làm quen với các thuộc tính [DataType], [Display] và [Column]; trong bài này chúng ta sẽ làm quen với các thuộc tính [Required], [StringLength], [RegularExpression] và [Range].

Mở tập tin Models / Book.cs và thêm các nội dung mới đến lớp Book (in đậm) như sau:

namespace MVCBooks.Models

{

    public class Book

    {

        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 mới được thêm đến các trường của lớp Book với mục đích:

  • Thuộc tính [Required] được thêm đến các trường của lớp Book nhằm bắt buộc người dùng phải nhập thông tin cho tất cả các trường này. Nếu người dùng để trống (ví dụ trường Genre), một cảnh báo sẽ xuất hiện (ví dụ The Genre field is required.) Một số trường có kiểu dữ liệu decimal, int, float, DateTime mặc định luôn luôn được yêu cầu nên không cần dùng thuộc tính [Required].
  • Thuộc tính [StringLength] quy định chiều dài tối đa của trường được áp dụng. Thuộc tính này có thể sử dụng với thuộc tính MinimumLength để quy định chiều dài tối thiểu của trường. Ví dụ trường Title sẽ có chiều dài tối đa (số ký tự) là 60 và chiều dài tối thiểu là 3.
  • Thuộc tính [Range] xác định giá trị thuộc một phạm vi xác định, ví dụ từ 1 đến 100.
  • Thuộc tính [RegularExpression] đi kèm với một biểu thức thường quyquy định các kí tự nào người dùng được phép nhập vào. Biểu thức thường quy có thể tham khảo tại https://ngocminhtran.com/regular-expression-co-ban/ Chúng ta áp dụng thuộc tính này đến trường Genre và Rating:
    • Đối với trường Genre, yêu cầu bắt buộc là ký tự đầu tiên phải viết hoa và chỉ cho phép các kí tự (a…z, A…Z) và khoảng trắng. Số và các kí tự đặc biệt (ví dụ dấu -) không được phép. Ví dụ: Abc là hợp lệ; abc và Ab-12 là không hợp lệ.
    • Đối với trường Rating, yêu cầu bắt buộc là ký tự đầu tiên phải viết hoa, các kí tự (a…z, A…Z), khoảng trắng, số và các kí tự đặc biệt (ví dụ dấu -) đều được được phép sử dụng. Ví dụ: Abc, Ab-12 là hợp lệ. abc không hợp lệ.
  • Trường Price áp dụng thuộc tính [DataType(DataType.Currency)] nên khi hiển thị sẽ xuất hiện dấu $ bên trái (mặc định).

Thực thi ứng dụng (chú ý mở lại JavaScript nếu còn tắt )

Nhấn liên kết Create New. Kiểm tra trường Title và Genre:

Kiểm tra các trường còn lại:

Cũng cần chú ý rằng có thể ứng dụng không cho phép chúng ta nhập dấu phẩy trong trường Price. Tham khảo các bước xử lý tại https://github.com/dotnet/AspNetCore.Docs/issues/4076#issuecomment-326590420

Chúng ta có thể kiểm tra lại bằng cách tắt JavaScript trên trình duyệt.

Input Tag Helper dùng các thuộc tính DataAnnotations và tạo ra các thuộc tính HTML cần thiết cho quá trình hợp lệ phía người dùng (nhờ jQuery hay JavaScript). Controller và các view không cần biết các luật hợp lệ là gì, tất cả chỉ tập trung tại lớp Book. Khi chúng ta cần thay đổi một số luật hợp lệ, chỉ cần thực hiện trên lớp Book. Các luật được tạo ra ở một nơi (lớp Book) và sử dụng ở nhiều nơi mà không cần phải lo lắng các thành phần khác. Điều này cho phép chúng ta dễ dàng bảo trì và mở rộng ứng dụng trong tương lai. Đây chính là nguyên tắc DRY.

Hợp lệ dữ liệu người dùng cũng được thực hiện trên trang (hay form) Edit.

Đến thời điểm này chúng ta có thể xuất bản ứng dụng web ASP.NET Core MVC.