Implementing Validation in ASP.NET Core MVC
This tutorial explores how to implement robust data validation in your ASP.NET Core MVC applications. Proper validation ensures data integrity and provides a better user experience by giving immediate feedback on input errors.
Client-Side vs. Server-Side Validation
Validation in ASP.NET Core MVC can be performed on both the client-side (in the browser) and the server-side (on the web server). Both are crucial for a complete validation strategy:
- Client-Side Validation: Provides immediate feedback to the user as they fill out a form, improving usability and reducing unnecessary server requests.
- Server-Side Validation: Is the ultimate safeguard. It ensures data integrity even if client-side validation is bypassed or disabled.
Using Data Annotations
The most common and recommended way to implement validation in ASP.NET Core is by using data annotations from the System.ComponentModel.DataAnnotations
namespace. These attributes are applied directly to your model properties.
Common Validation Attributes:
[Required]
: Marks a property as mandatory.[StringLength(int maxLength, int minLength = 0)]
: Validates the length of a string.[RegularExpression(string pattern)]
: Validates a string against a regular expression.[EmailAddress]
: Validates that a string is a valid email format.[Url]
: Validates that a string is a valid URL.[Range(int minimum, int maximum)]
: Validates that a numeric value falls within a specified range.[Compare(string otherProperty)]
: Compares one property to another (e.g., for password confirmation).[DataType(DataType)]
: Provides semantic information about a property (e.g.,DataType.Password
,DataType.EmailAddress
). This is often used for UI hints but can also trigger specific client-side validation.
Example Model with Data Annotations
Consider a CreateProductViewModel
:
using System.ComponentModel.DataAnnotations;
public class CreateProductViewModel
{
[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]
[Range(0.01, 1000.00, ErrorMessage = "Price must be between 0.01 and 1000.00.")]
[DataType(DataType.Currency)]
public decimal Price { get; set; }
[EmailAddress(ErrorMessage = "Please enter a valid email address.")]
public string ContactEmail { get; set; }
[Url(ErrorMessage = "Please enter a valid website URL.")]
public string Website { get; set; }
}
Using Validation in Controllers
In your controller actions, you can check the validity of the model using the ModelState.IsValid
property. This property is automatically populated based on the data annotations applied to your model and the incoming request data.
Controller action example:
using Microsoft.AspNetCore.Mvc;
public class ProductsController : Controller
{
public IActionResult Create()
{
return View();
}
[HttpPost]
public IActionResult Create(CreateProductViewModel model)
{
if (ModelState.IsValid)
{
// Process the valid model data (e.g., save to database)
// ...
return RedirectToAction("Index"); // Redirect to a success page
}
// If ModelState is not valid, re-render the view with validation errors
return View(model);
}
}
Displaying Validation Messages in Views
To display validation messages to the user, you can use the <validation-summary>
and <span class="field-validation-valid">
(or field-validation-error
) tag helpers in your Razor views.
Razor view example (Create.cshtml
):
@model CreateProductViewModel
@{
ViewData["Title"] = "Create Product";
}
Create New Product
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Note: The _ValidationScriptsPartial.cshtml
typically includes the necessary JavaScript libraries (like jQuery Validate and the unobtrusive validation adapter) for client-side validation to function.
Custom Validation
For more complex validation rules that cannot be expressed with built-in attributes, you can create custom validation attributes or use the IValidatableObject
interface.
Custom Validation Attribute Example:
To create a custom validation attribute, inherit from ValidationAttribute
and override the IsValid
method.
using System.ComponentModel.DataAnnotations;
public class NonNegativeAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
if (value is decimal decimalValue)
{
return decimalValue >= 0;
}
if (value is int intValue)
{
return intValue >= 0;
}
// Handle other numeric types as needed or return false
return false;
}
}
// Usage in model:
// [NonNegative(ErrorMessage = "Value cannot be negative.")]
// public decimal Discount { get; set; }
Conclusion
Effective validation is a cornerstone of building reliable web applications. By leveraging data annotations and understanding the interplay between client-side and server-side validation, you can create robust and user-friendly forms in ASP.NET Core MVC.