Data Validation in ASP.NET Core MVC
This document provides a comprehensive guide to implementing data validation in ASP.NET Core MVC applications. Effective data validation is crucial for ensuring data integrity, security, and a good user experience.
Validation Attributes
ASP.NET Core MVC uses a declarative approach to validation using data annotation attributes. These attributes are applied to properties of your model classes to define validation rules.
Common Validation Attributes:
[Required]
: Ensures that a property is not null or empty.[StringLength(maxLength, MinimumLength = minLength)]
: Validates the length of a string property.[Range(minimum, maximum)]
: Validates that a numeric or date property falls within a specified range.[RegularExpression(pattern)]
: Validates a string property against a regular expression pattern.[EmailAddress]
: Validates that a string is a valid email address format.[Url]
: Validates that a string is a valid URL format.[Compare("otherProperty")]
: Compares the value of one property to another (e.g., for password confirmation).[Phone]
: Validates that a string is a valid phone number format.
Example Model with Validation Attributes:
using System.ComponentModel.DataAnnotations;
public class ProductViewModel
{
[Required(ErrorMessage = "Product name is required.")]
[StringLength(100, MinimumLength = 3, ErrorMessage = "Product name must be between 3 and 100 characters.")]
public string Name { get; set; }
[Required(ErrorMessage = "Price is required.")]
[Range(0.01, 10000.00, ErrorMessage = "Price must be between 0.01 and 10000.00.")]
[DataType(DataType.Currency)]
public decimal Price { get; set; }
[EmailAddress(ErrorMessage = "Invalid email address format.")]
public string ContactEmail { get; set; }
[Url(ErrorMessage = "Please enter a valid URL.")]
public string Website { get; set; }
}
Client-Side Validation
For client-side validation to work, you need to include the necessary JavaScript files and enable unobtrusive JavaScript validation in your application.
Steps for Client-Side Validation:
- Ensure you have added the appropriate NuGet packages (e.g.,
Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation
if you're not using MVC views directly). - In your layout file (e.g.,
_Layout.cshtml
), include the following scripts in the<head>
or before the closing</body>
tag:
You might need to adjust paths based on your project setup.<script src="~/lib/jquery/dist/jquery.min.js"></script> <script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script> <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
- In your views, use the
<div asp-validation-for="PropertyName"></div>
helper to render validation messages. - Use the
<div asp-validation-summary="ModelOnly"></div>
helper at the top of your form to display validation errors that are not associated with a specific property (e.g., `ModelState.AddModelError`).
Example View (Create.cshtml
):
@model ProductViewModel
<form asp-action="Create" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Price"></label>
<input asp-for="Price" class="form-control" />
<span asp-validation-for="Price" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ContactEmail"></label>
<input asp-for="ContactEmail" class="form-control" />
<span asp-validation-for="ContactEmail" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Create Product</button>
</form>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Server-Side Validation
Server-side validation is essential for security and to catch any bypasses of client-side validation. In ASP.NET Core MVC, server-side validation is automatically performed when you use the [ValidateAntiForgeryToken]
attribute on your POST action methods and check ModelState.IsValid
.
Example Controller Action:
using Microsoft.AspNetCore.Mvc;
public class ProductsController : Controller
{
[HttpPost]
[ValidateAntiForgeryToken] // Important for security
public IActionResult Create(ProductViewModel model)
{
if (ModelState.IsValid)
{
// Save the product to the database
// ...
return RedirectToAction("Index"); // Redirect on success
}
// If ModelState is not valid, re-render the view with errors
return View(model);
}
}
ModelState.IsValid
after attempting to bind the model to the request data. If it's false, return the view with the invalid model to display the errors to the user.
Custom Validation Attributes
You can create your own custom validation attributes by inheriting from ValidationAttribute
and overriding the IsValid
method.
Example of a Custom Attribute (e.g., for a unique username):
using System.ComponentModel.DataAnnotations;
public class UniqueUsernameAttribute : ValidationAttribute
{
private readonly UserService _userService; // Assume a service to check uniqueness
public UniqueUsernameAttribute(UserService userService)
{
_userService = userService;
ErrorMessage = "Username is already taken.";
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value == null)
{
return ValidationResult.Success; // Not required, so null is valid
}
string username = value.ToString();
if (_userService.IsUsernameUnique(username))
{
return ValidationResult.Success;
}
else
{
return new ValidationResult(ErrorMessage);
}
}
}
You would then need to register UserService
in your dependency injection container and potentially find a way to inject it into the attribute or use a factory pattern.
Validation Summary
Data validation is a cornerstone of robust web applications. By leveraging data annotation attributes, client-side scripting, and server-side checks, you can build secure and user-friendly applications with ASP.NET Core MVC.