Data validation is a critical aspect of web application development. It ensures that the data submitted by users conforms to expected formats and constraints, preventing errors, improving data integrity, and enhancing the user experience. ASP.NET Core MVC provides a robust and flexible framework for implementing data validation on both the client-side and server-side.
[Required], [StringLength], [EmailAddress], [Range]).IValidatableObject: An interface that allows you to implement custom, cross-property validation logic within your model.TryValidateModel() and TryValidateObject(): Methods used in controllers to explicitly trigger validation for a model instance.Let's consider a simple example of a model with validation attributes:
public class Product
{
public int Id { get; set; }
[Required(ErrorMessage = "Product name is required.")]
[StringLength(100, ErrorMessage = "Product name cannot exceed 100 characters.")]
public string Name { get; set; }
[Required(ErrorMessage = "Price is required.")]
[Range(0.01, double.MaxValue, ErrorMessage = "Price must be a positive value.")]
public decimal Price { get; set; }
[EmailAddress(ErrorMessage = "Invalid email address format.")]
public string ContactEmail { get; set; }
}
In your controller, you can check the validity of the model before processing it:
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;
public class ProductController : Controller
{
// GET: Product/Create
public IActionResult Create()
{
return View();
}
// POST: Product/Create
[HttpPost]
public IActionResult Create(Product product)
{
if (ModelState.IsValid)
{
// Save the product to the database
// ...
return RedirectToAction(nameof(Index)); // Redirect to a success page
}
// If validation fails, redisplay the form with errors
return View(product);
}
// Example Index action
public IActionResult Index()
{
// Placeholder for displaying products
return View(new List<Product>());
}
}
Your view (e.g., Create.cshtml) needs to render validation messages. ASP.NET Core MVC provides helper tags for this:
@model YourApplication.Models.Product
<h2>Create New Product</h2>
<form asp-action="Create" method="post">
<div asp-validation-summary="ModelOnly" class="validation-summary"></div>
<div class="example-form">
<div class="form-group">
<label asp-for="Name"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="field-validation-error"></span>
</div>
<div class="form-group">
<label asp-for="Price"></label>
<input asp-for="Price" class="form-control" />
<span asp-validation-for="Price" class="field-validation-error"></span>
</div>
<div class="form-group">
<label asp-for="ContactEmail"></label>
<input asp-for="ContactEmail" class="form-control" />
<span asp-validation-for="ContactEmail" class="field-validation-error"></span>
</div>
<button type="submit" class="btn">Create Product</button>
</div>
</form>
@section Scripts {
<!-- Include jQuery and the validation plugin -->
<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>
}
For client-side validation to work, you need to ensure that the necessary JavaScript libraries are included in your project and referenced in your layout or specific view. Typically, this involves:
Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation (if not already present), Microsoft.AspNetCore.App, Microsoft.jQuery.Unobtrusive.Ajax, Microsoft.jQuery.Unobtrusive.Validation, and jQuery.Validation._Layout.cshtml or specific view includes references to jQuery and the validation scripts. The @section Scripts in the example above handles this for a single view.When ModelState.IsValid is false on the server, the validation attributes are rendered as HTML data attributes (e.g., data-val="true", data-val-required="..."). The unobtrusive JavaScript then interprets these attributes and applies the validation logic in the browser.
You can create custom validation attributes by inheriting from ValidationAttribute or implement complex validation logic using IValidatableObject.
using System.ComponentModel.DataAnnotations;
public class NotFutureDateAttribute : ValidationAttribute
{
public NotFutureDateAttribute() : base("Date cannot be in the future.") {}
public override bool IsValid(object value)
{
if (value is DateTime date)
{
return date < DateTime.Today;
}
return true; // Not a DateTime, so it's valid for this attribute
}
}
// Apply it to your model:
// [NotFutureDate(ErrorMessage = "Please enter a past or present date.")]
// public DateTime BirthDate { get; set; }
IValidatableObject Example:
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
public class UserProfile : IValidatableObject
{
public string Username { get; set; }
public string Password { get; set; }
public string ConfirmPassword { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var results = new List<ValidationResult>();
if (!string.IsNullOrEmpty(Password) && !string.IsNullOrEmpty(ConfirmPassword) && Password != ConfirmPassword)
{
results.Add(new ValidationResult("Passwords do not match.", new[] { nameof(ConfirmPassword) }));
}
// Add other cross-property validations as needed
// if (Username == "admin" && Password == "12345") { ... }
return results;
}
}
To use IValidatableObject, simply include it in your controller:
[HttpPost]
public IActionResult Register(UserProfile userProfile)
{
if (ModelState.IsValid) // This automatically calls Validate() for IValidatableObject
{
// ...
}
return View(userProfile);
}
Mastering data validation in ASP.NET Core MVC is key to building robust and user-friendly applications. By leveraging data annotations, custom validation, and the seamless integration of client-side and server-side checks, you can ensure data quality and provide a smooth experience for your users.
Explore the official ASP.NET Core Validation Documentation for more advanced scenarios and details.