Create Custom Client Side Validation Attribute in ASP.NET Core

ASP.NET Core comes with a set of validation attributes that can be used to
perform basic validations in your application. At times the inbuilt validation
attributes doesn't meet your requirements and you need something customized as
per your validation criteria. Luckily, you can easily create your own validation
attributes that perform client side as well as server side validations. This
article shows how.
Suppose you have a Customer model class as shown below :
public class Customer
{
[Required]
[StringLength(5,MinimumLength =5)]
public string CustomerID { get; set; }
[Required]
[StringLength(40)]
public string CompanyName { get; set; }
[Required]
[StringLength(40)]
public string ContactName { get; set; }
[Required]
public string Country { get; set; }
}
Further assume that you want to validate the Country property against certain
countries decided by some custom logic. Moreover similar validation is needed in
multiple model classes.
In such cases you can create your own validation attribute. The custom
validation attribute can perform validation on server side alone or on client
side also.
To create such a custom validation attribute you need to do a few things :
- Create an attribute class that inherits from ValidationAttribute base
class and override IsValid() method.
- Implement IClientModelValidator interface and implement AddValidation()
method if you wish to support client side validation.
- Write the jQuery code that will perform the client side validation and
hook it into the ASP.NET Core's client side validation system.
Let's follow these steps in a sample attribute.
Creating a custom validation attribute class
In order to create a custom validation attribute you need to create a class
that inherits from ValidationAttribute base class and override its IsValid()
method. The following code shows CountryAttribute class that does just that :
public class CountryAttribute : ValidationAttribute
{
protected override ValidationResult IsValid
(object value, ValidationContext validationContext)
{
string country = value.ToString();
if (country != "USA" && country !=
"UK" && country != "India")
{
return new ValidationResult("Invalid country.
Valid values are USA, UK, and India.");
}
return ValidationResult.Success;
}
}
As you can see, the IsValid() method receives two parameters - value and
validationContext. The value object parameter supplies the property value on
which the Country attribute is used. Inside, you simply check whether the
country is USA, UK, or India. If not, you return a ValidationResult() object
wrapping an error message. In this case our custom validation criteria is quite
simple but you can add whatever validation logic you want as per your
application requirement.
If the check passes our validation criteria we return
ValidationResult.Success indicating a successful validation.
Once created you can apply the [Country] attribute on top of the Country
property as shown below :

At this stage have implemented server side validation only. You can
check whether the country is valid or not like this :
[HttpPost]
public IActionResult OnPost(Customer model)
{
if(ModelState.IsValid)
{
ViewData["Message"] = "Success !!!";
}
return View("Index", model);
}
The IsValid property of ModelStare will return false if you enter an invalid
country. You can also display the validation error message using validation tag
helper and validation summary tag helper. The following figure shows a sample
view that displays the validation error message :

Implementing IClientModelValidator interface
Now let's add client side validation capabilities to our custom validation
attribute. To do so implement IClientModelValidator interface on the
CountryAttribute class as shown below :
public class CountryAttribute : ValidationAttribute,
IClientModelValidator
{
protected override ValidationResult IsValid(object value,
ValidationContext validationContext)
{
...
}
public void AddValidation
(ClientModelValidationContext context)
{
context.Attributes.Add("data-val", "true");
context.Attributes.Add("data-val-country",
"Invalid country. Valid values are USA, UK, and India.");
}
}
Since CountryAttribute class implements IClientModelValidator interface you
need to write the AddValidation() method. This method sets certain client side
custom data attributes or data-* attributes that are used by the validation
system. Specifically we set the data-val and data-val-country attributes. The
later data attribute specifies the client side error message.
Adding the above custom data attributes simply tells the framework to emit
them when the view is rendered in the browser. They don't perform any validation
by themselves. So, you need to hook a jQuery function that does the client side
validation for you.
Writing jQuery code for client side validation
Add a new JavaScript file named CountryValidate.js into the wwwroot folder as
shown below :

Then write the following code into the CountryValidate.js file :
jQuery.validator.addMethod("country",
function (value, element, param) {
if (value != "USA" && value != "UK"
&& value != "India") {
return false;
}
else {
return true;
}
});
jQuery.validator.unobtrusive.adapters.addBool("country");
The above code adds a method to jQuery validation library. It uses addMethod()
method to specify our own validation function. The validation function receives
the value entered in the country textbox. It then performs the validation and
returns a boolean value.
Finally, this validation function is hooked into the validation library using
the addBool() method.
You now need to reference the Countryvalidate.js in your Index view :
<script src="~/scripts/jquery.js"></script>
<script src="~/scripts/jquery.validate.js"></script>
<script src="~/scripts/jquery.validate.unobtrusive.js"></script>
<script src="~/Scripts/CountryValidate.js"></script>
Now run the application and check whether client side validation is working
as expected.
That's it for now ! Keep coding !!