In this small blog post, I will show you how to create your own Validation attribute in ASP.NET Core to tailor-made your validation rules.
Validation attributes
So that we are on the same page, ASP.NET Core offers a set of validation attributes that can be used to validate the data that is being sent to the server. These attributes are used to decorate the properties of the model class. This also applies to Blazor if you want for form validation. Here is a small example:
public class Person
{
[Required]
public string Name { get; set; }
[Required]
[Range(18, 99)]
public int Age { get; set; }
}
Required
means that Name
has to be set and not empty (or full of whitespaces). Range
means that Age
has to be between 18 and 99. If you want to know more about the validation attributes, you can check out the documentation. So there are a number of attributes that can be used to validate the data. But what if you want to validate the data in a more complex way? For example, you have a model that contains a DateTime
object that should be in the future? Here is where we can hook in and write our own validation attributes.
Custom validation attributes
It is quite straightforward to write your own validation attributes. You can inherit from the ValidationAttribute
class and override the IsValid
method. This method takes an object as a parameter and returns a boolean. The object is the value that is being validated. In the example below, we are validating that the DateTime
object is in the future. If it is, we return true
, otherwise we return false
and add an error to the ValidationContext
object. The ValidationContext
object contains the model that is being validated and the DisplayName
of the property that is being validated. This is used to display the error message to the user.
public class FutureDateAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value is DateTime date)
{
if (date > DateTime.Now)
{
return ValidationResult.Success;
}
}
return new ValidationResult($"The {validationContext.DisplayName} field must be a future date.");
}
}
The usage of this attribute is the same as the other validation attributes. You can decorate the property with the attribute and you are good to go. Here is an example:
public class BlogPost
{
[FutureDate]
public DateTime ScheduleDate { get; set; }
}
Of course, you can add further configuration, like the DateTime
has to be UTC, or add an optional error message. Here is how you can do that:
public class FutureDateAttribute : ValidationAttribute
{
public bool Utc { get; set; } = true;
protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
{
if (value is null)
{
return ValidationResult.Success;
}
var now = UseUtc ? DateTime.UtcNow : DateTime.Now;
return (DateTime)value <= now
? new ValidationResult("The selected date must be in the future.")
: ValidationResult.Success;
}
}
Here the usage of the attribute:
public class BlogPost
{
[FutureDate(Utc = false)]
public DateTime ScheduleDate { get; set; }
}
Conclusion
In this article, we have seen how we can write our own validation attributes. This is useful if you want to validate the data in a more complex way. For example, you want to validate that a DateTime
object is in the future.