Create your own Validationattribute in ASP.NET Core

27/04/2023
.NETASP.NETC#

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.

1
An error has occurred. This application may no longer respond until reloaded. Reload x