# Data Annotation (Model Validation) ## 官方文件 主要: https://learn.microsoft.com/zh-tw/aspnet/core/tutorials/first-mvc-app/validation?view=aspnetcore-8.0 包含其他: https://learn.microsoft.com/zh-tw/aspnet/core/tutorials/first-mvc-app/validation?view=aspnetcore-8.0 ## 原理 用戶端驗證 -> 產生JS驗證碼,減少發送請求到伺服器的步驟浪費。 Client-Side Validation: Data annotations automatically generate **client-side validation** logic, reducing server round-trips and improving user experience. For example, [Required], [EmailAddress], and [StringLength] will generate JavaScript validation code in Razor views. ## 範例 Here are some real-world examples of how you might use data annotations with ErrorMessage in an ASP.NET Core MVC application: ### Example 1: User Registration Form In a user registration form, you might want to ensure that the username, email, and password fields are filled out correctly and **adhere to specific validation rules**. ```csharp= public class RegisterViewModel { [Required(ErrorMessage = "Username is required.")] [StringLength(20, ErrorMessage = "Username must be between 5 and 20 characters long.", MinimumLength = 5)] public string Username { get; set; } [Required(ErrorMessage = "Email is required.")] [EmailAddress(ErrorMessage = "Please enter a valid email address.")] public string Email { get; set; } [Required(ErrorMessage = "Password is required.")] [StringLength(100, ErrorMessage = "Password must be at least 8 characters long.", MinimumLength = 8)] [DataType(DataType.Password)] public string Password { get; set; } [Required(ErrorMessage = "Please confirm your password.")] [DataType(DataType.Password)] [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] public string ConfirmPassword { get; set; } } ``` ### Example 2: Product Entry Form When adding a new product to an inventory system, you might want to validate fields like name, price, and stock quantity. ```csharp= public class ProductViewModel { [Required(ErrorMessage = "Product name is required.")] [StringLength(50, ErrorMessage = "Product name cannot exceed 50 characters.")] public string Name { get; set; } [Required(ErrorMessage = "Price is required.")] [Range(0.01, 10000.00, ErrorMessage = "Price must be between $0.01 and $10,000.00.")] public decimal Price { get; set; } [Required(ErrorMessage = "Stock quantity is required.")] [Range(0, int.MaxValue, ErrorMessage = "Stock quantity cannot be negative.")] public int Stock { get; set; } } ``` ### Example 3: Contact Form A contact form might include fields like name, email, phone number, and message, all of which need to be validated. ```csharp= public class ContactViewModel { [Required(ErrorMessage = "Your name is required.")] [StringLength(100, ErrorMessage = "Name cannot exceed 100 characters.")] public string Name { get; set; } [Required(ErrorMessage = "Email is required.")] [EmailAddress(ErrorMessage = "Please enter a valid email address.")] public string Email { get; set; } [Phone(ErrorMessage = "Please enter a valid phone number.")] public string PhoneNumber { get; set; } [Required(ErrorMessage = "Message is required.")] [StringLength(500, ErrorMessage = "Message cannot exceed 500 characters.")] public string Message { get; set; } } ``` ### Example 4: Login Form A simple login form might require validation on the email and password fields. ```csharp public class LoginViewModel { [Required(ErrorMessage = "Email is required.")] [EmailAddress(ErrorMessage = "Please enter a valid email address.")] public string Email { get; set; } [Required(ErrorMessage = "Password is required.")] [DataType(DataType.Password)] public string Password { get; set; } } ``` Example 5: Event Registration Form An event registration form might require the user's name, email, and a selection of the event date. ```csharp public class EventRegistrationViewModel { [Required(ErrorMessage = "Your name is required.")] [StringLength(100, ErrorMessage = "Name cannot exceed 100 characters.")] public string Name { get; set; } [Required(ErrorMessage = "Email is required.")] [EmailAddress(ErrorMessage = "Please enter a valid email address.")] public string Email { get; set; } [Required(ErrorMessage = "Please select an event date.")] [DataType(DataType.Date)] public DateTime EventDate { get; set; } } ``` ## 常用 Common Data Annotations Here’s a list of some of the most common data annotations used in .NET Core: 1. [Required] Ensures that the property is not left empty. Example: ```csharp [Required(ErrorMessage = "Name is required.")] public string Name { get; set; } ``` 2. [StringLength] - Sets a maximum and optionally a minimum length for a string property. - Example: ```csharp [StringLength(50, MinimumLength = 5, ErrorMessage = "Name must be between 5 and 50 characters.")] public string Name { get; set; } ``` 3. [MaxLength] Sets the maximum allowable length of a string or array. Example: ```csharp= [MaxLength(100, ErrorMessage = "Description can't exceed 100 characters.")] public string Description { get; set; } ``` 4. [MinLength] - Sets the minimum allowable length of a string or array. - Example: ```csharp [MinLength(10, ErrorMessage = "Description must be at least 10 characters long.")] public string Description { get; set; } ``` 5. [Range] - Validates that a number or date falls within a specified range. - Example: ```csharp [Range(18, 65, ErrorMessage = "Age must be between 18 and 65.")] public int Age { get; set; } ``` 6. [RegularExpression] - Validates that the value of a property matches a specified regular expression pattern. - Example: ```csharp [RegularExpression(@"^[a-zA-Z0-9]*$", ErrorMessage = "Only alphanumeric characters are allowed.")] public string Username { get; set; } ``` 7. [EmailAddress] - Validates that the value is a valid email address format. - Example: ``` [EmailAddress(ErrorMessage = "Invalid email address.")] public string Email { get; set; } ``` 8. [Phone] - Validates that the value is a valid phone number format. - Example: ```csharp [Phone(ErrorMessage = "Invalid phone number.")] public string PhoneNumber { get; set; } ``` 9. [Compare] - Compares two properties and validates that their values are equal. - Often used for confirming passwords. - Example: ```csharp [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] public string ConfirmPassword { get; set; } 10. [CreditCard] - Validates that the value is a valid credit card number format. - Example: ```csharp [CreditCard(ErrorMessage = "Invalid credit card number.")] public string CreditCardNumber { get; set; } ``` 11. [Url] - Validates that the value is a valid URL format. - Example: ```csharp [Url(ErrorMessage = "Invalid URL.")] public string WebsiteUrl { get; set; } ``` 12. [DataType] - Specifies the type of data, such as `Date`, `Time`, `Currency`, `Password`, etc. - Helps with rendering the correct HTML input types and formatting. - Example: ```csharp [DataType(DataType.Date)] public DateTime BirthDate { get; set; } ``` 13. [Display] - Specifies how the data field is displayed. - Commonly used to set display names, prompts, or formatting strings. - Example: ```csharp [Display(Name = "Full Name")] public string Name { get; set; } ``` 14. [DisplayFormat] kotlin 複製程式碼 - Specifies formatting options for the data field. - Often used for formatting dates, numbers, etc. - Example: ```csharp= [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] public DateTime DateOfBirth { get; set; } ``` ### Usage Example Here’s a complete example of a model using several of these data annotations: ```csharp= public class UserViewModel { [Required(ErrorMessage = "Name is required.")] [StringLength(50, ErrorMessage = "Name must be less than 50 characters.")] public string Name { get; set; } [EmailAddress(ErrorMessage = "Invalid email address.")] public string Email { get; set; } [Phone(ErrorMessage = "Invalid phone number.")] public string PhoneNumber { get; set; } [Range(18, 65, ErrorMessage = "Age must be between 18 and 65.")] public int Age { get; set; } [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] public string ConfirmPassword { get; set; } [DataType(DataType.Password)] public string Password { get; set; } } ``` ## 用法 Usage To display the validation error messages to the user in an ASP.NET Core MVC application, **you can use the ModelState and ValidationSummary or individual ValidationMessageFor helpers** in your view. -> 重點:ModelState + ValidationSummary(整體)/ValidationMessageFor(個體) ### 1. Model Definition You've already defined the model with validation attributes: ```csharp public class UserViewModel { [Required(ErrorMessage = "Username is required.")] [StringLength(20, ErrorMessage = "Username must be between 5 and 20 characters long.", MinimumLength = 5)] public string Username { get; set; } } ``` ### 2. Controller Action In your controller, when you post the form data, you should check if the model state is valid: ```csharp [HttpPost] public IActionResult Register(UserViewModel model) { if (ModelState.IsValid) { // Proceed with registration logic return RedirectToAction("Success"); } // If we got this far, something failed; redisplay the form with validation errors return View(model); } ``` ### 3. View (Razor Page) In your view, you can use ValidationSummary and ValidationMessageFor to display error messages. ```csharp @model UserViewModel <form asp-action="Register" method="post"> <div class="form-group"> <label asp-for="Username"></label> <input asp-for="Username" class="form-control" /> <span asp-validation-for="Username" class="text-danger"></span> </div> <button type="submit" class="btn btn-primary">Register</button> </form> <div> @Html.ValidationSummary(false, "", new { @class = "text-danger" }) </div> ``` ### Explanation: **ValidationMessageFor**: The asp-validation-for tag helper is used to display the validation error message for a specific property, like Username. **ValidationSummary**: This displays a summary of all validation errors in the form. If you set the first parameter to false, it only shows model-level errors and not property-specific ones. If set to true, it shows all errors. ### Result: If the user submits the form without filling in the username or with a username that doesn't meet the requirements, the corresponding error message ("Username is required." or "Username must be between 5 and 20 characters long.") will be displayed next to the input field.