IValidatableObject: Class-Level Validation in ASP.NET Core

This blog is going to explain what class-level validation is in ASP.NET Core. ASP.NET Core has some built-in validation attributes, such as [Required], [Range], [EmailAddress]. But those verification attributes are not enough all the time. Sometimes we need to validate based on conditions. In that case, you can inherit and validate the IValidatableObject for the class. This validation only works in the class where you implement the IValidatableObject.

This example illustrates how to check the text box content based on the checkbox value. That means if the checkbox is checked it should validate whether the text box is empty or not. Let's look at that step by step.

Step 1:
The following is a SampleModel class. In this class, I implemented IValidatableObject. This class has only two properties, Join and PhoneNumber. Join property is a bool and PhoneNumber is a string. Also, the Validate method is implemented from IValidatableObject. In the method, I have checked whether the Join is true and the PhoneNumber is empty. If it is true, it will trigger the exception.

SampleModel.cs
public class SampleModel : IValidatableObject
{
    public bool Join { get; set; }
    public  string PhoneNumber { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (Join && string.IsNullOrWhiteSpace(PhoneNumber))
        {
            yield return new ValidationResult( "Please enter the phone number",
                new[] { nameof(PhoneNumber) });
        }
    }
}

Step 2:
In the second step, I created the view page. Here I have used the SampleModel to bind the elements. Finally, the submit button to submit the page to the controller action. All the elements have been put inside the form tag helper so that it will send all the user input to the controller model.

And most importantly, I added the span element with asp-validation-for attribute. The PhoneNumber property is assigned to the asp-validation-for attribute, so it will display a validation error message.

Index.cshtml
@{
    ViewData["Title"] = "IValidatableObject: Class-Level Validation";
}
@model SampleModel

@{
<form asp-controller="Home" asp-action="Index" method="post">
    <table>
        <tr>
            <td> Do you want to join the conference?<input asp-for="Join" type="checkbox" />
            </td>
        </tr>
        <tr>
            <td> Enter Phone Number: <input type="text" asp-for="PhoneNumber"> 
	    <span asp-validation-for="PhoneNumber" class="text-danger"></span>
            </td>
        </tr>
    </table>
    <input type="submit" value="Submit" />
</form>
}

Step 3:
The final step age is the controller action method . There are two modes, one is Index GET and the other is Index Post. The GET method passes the empty SampleModel to the sample.cshtml view. In the POST Index method, receives the SampleModel values by parameter. If ModelState is valid, it will return to the message page, otherwise it will return to the same page with the validation message.

public IActionResult Index()
{
    SampleModel sample = new SampleModel();
    return View(sample);
}

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(SampleModel sample)
{            
    if (ModelState.IsValid)
    {
        return View("Message");
    }
    return View(sample);
}

Output
The following is the output of the above code. If the user checks the checkbox and clicks the submit button, it triggers the validation message. But when the user unchecked the checkbox and clicked on the submit button it returned to the message page. That means the validation is not triggered.

I hope this helps you. Keep coding.

Comments

Popular posts from this blog

Entity Framework Core (EF) with SQL Server LocalDB

Creating a C# Azure Function with Visual Studio: Step-by-Step Guide

Exploring EventCallback in Blazor: Building Interactive Components