# 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.