Getting Started with Validation in ASP.NET Core MVC

Server-side validation is crucial for ensuring data integrity and providing a robust user experience in your ASP.NET Core MVC applications. This tutorial will guide you through implementing various validation techniques.

1. Data Annotations for Validation

The most common and declarative way to implement validation in ASP.NET Core is by using data annotations. These attributes are applied directly to your model properties.

Common Data Annotations:

Example Model:

Customer.cs

using System.ComponentModel.DataAnnotations;

public class Customer
{
    [Required(ErrorMessage = "Please enter your first name.")]
    [StringLength(50, ErrorMessage = "First name cannot exceed 50 characters.")]
    public string FirstName { get; set; }

    [Required(ErrorMessage = "Please enter your last name.")]
    [StringLength(50, ErrorMessage = "Last name cannot exceed 50 characters.")]
    public string LastName { get; set; }

    [Required(ErrorMessage = "Please enter your email address.")]
    [EmailAddress(ErrorMessage = "Invalid email address format.")]
    public string Email { get; set; }

    [Required(ErrorMessage = "Please enter your age.")]
    [Range(18, 99, ErrorMessage = "Age must be between 18 and 99.")]
    public int Age { get; set; }

    [RegularExpression(@"^\d{10}$", ErrorMessage = "Phone number must be 10 digits.")]
    public string PhoneNumber { get; set; }
}
        

2. Controller and View Integration

ASP.NET Core MVC automatically integrates data annotations with your controllers and views. When a form is submitted, the model binder attempts to validate the incoming data against the defined attributes.

Controller Action:

CustomerController.cs

using Microsoft.AspNetCore.Mvc;

public class CustomerController : Controller
{
    // GET: /Customer/Create
    public IActionResult Create()
    {
        return View();
    }

    // POST: /Customer/Create
    [HttpPost]
    public IActionResult Create(Customer customer)
    {
        // ModelState.IsValid checks if all validation rules are met
        if (ModelState.IsValid)
        {
            // Process the valid customer data (e.g., save to database)
            // For this example, we'll just redirect
            return RedirectToAction("Success");
        }

        // If validation fails, return the view with errors
        return View(customer);
    }

    public IActionResult Success()
    {
        return View();
    }
}
        

View (Create.cshtml):

The Tag Helper asp-validation-for is essential for displaying validation messages associated with specific model properties. asp-validation-summary displays all validation errors.

Views/Customer/Create.cshtml

@model Customer

@{
    ViewData["Title"] = "Create Customer";
}

Create New Customer

@section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} }

View (Success.cshtml):

Views/Customer/Success.cshtml

@{
    ViewData["Title"] = "Success";
}

Customer Created Successfully!

Thank you for submitting your information.

3. Client-Side Validation

By default, ASP.NET Core MVC also enables client-side validation when you include the necessary JavaScript files. This provides immediate feedback to the user without a full page reload.

Ensure that your layout file (e.g., _Layout.cshtml) includes the following section near the end of the <body> tag:


<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.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>
<script src="~/js/site.js" asp-append-version="true"></script>
        

And in your specific view (Create.cshtml), the @section Scripts block ensures these are rendered:


@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
        
Tip: The _ValidationScriptsPartial.cshtml file typically contains the necessary includes for jQuery Validation and Unobtrusive Validation.

4. Custom Validation Attributes

For more complex validation scenarios, you can create custom validation attributes by inheriting from ValidationAttribute.

Example: AtLeastOneCapitalLetterAttribute

Attributes/AtLeastOneCapitalLetterAttribute.cs

using System.ComponentModel.DataAnnotations;

public class AtLeastOneCapitalLetterAttribute : ValidationAttribute
{
    public AtLeastOneCapitalLetterAttribute()
    {
        ErrorMessage = "The field must contain at least one capital letter.";
    }

    public override bool IsValid(object value)
    {
        if (value == null || string.IsNullOrEmpty(value.ToString()))
        {
            return true; // Allow empty/null values if not marked as Required
        }

        string input = value.ToString();
        foreach (char c in input)
        {
            if (char.IsUpper(c))
            {
                return true;
            }
        }
        return false;
    }
}
        

Using the Custom Attribute:

Apply it to your model property:


using System.ComponentModel.DataAnnotations;

public class UserProfile
{
    [Required]
    [AtLeastOneCapitalLetter]
    public string Password { get; set; }
}
        

5. Remote Validation

Remote validation allows you to validate a property's value by making an asynchronous call to a specific action method on your server. This is useful for checking if a username is already taken, for example.

Model:


using System.ComponentModel.DataAnnotations;

public class RegistrationModel
{
    [Required]
    [Remote(action: "CheckUsername", controller: "Account")]
    public string Username { get; set; }

    [Required]
    public string Email { get; set; }
}
        

Controller Action:


using Microsoft.AspNetCore.Mvc;

public class AccountController : Controller
{
    // Example: Simulate checking if username exists
    public JsonResult CheckUsername(string username)
    {
        bool isUsernameTaken = (username.ToLower() == "admin"); // Simulate taken username

        if (isUsernameTaken)
        {
            return Json(data: false, "Username is already taken.");
        }
        else
        {
            return Json(data: true);
        }
    }
}
        

Client-side remote validation requires the jquery.validate.unobtrusive.js and related dependencies.

Tip: For complex validation logic or when dealing with large amounts of data, consider implementing validation in your service layer rather than directly in the controller.

Mastering validation in ASP.NET Core MVC is key to building secure and user-friendly web applications. By leveraging data annotations, custom attributes, and remote validation, you can ensure data quality and provide effective feedback to your users.