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.

Note: Data validation can be performed on both the client-side (in the browser) and the server-side (on the server). It's best practice to implement validation on both sides for maximum security and usability.

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:

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:

  1. Ensure you have added the appropriate NuGet packages (e.g., Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation if you're not using MVC views directly).
  2. In your layout file (e.g., _Layout.cshtml), include the following scripts in the <head> or before the closing </body> tag:
    
    <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>
                        
    You might need to adjust paths based on your project setup.
  3. In your views, use the <div asp-validation-for="PropertyName"></div> helper to render validation messages.
  4. 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);
    }
}
            
Tip: Always check 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.

Warning: Never rely solely on client-side validation. Always implement server-side validation to protect your application from malicious attacks and ensure data integrity.