liveBook · Manning

Validation attribute

As explained in Building Web APIs with ASP.NET Core

A custom validation attribute is an application-defined attribute that implements a domain-specific input-validation rule.

A custom validation attribute puts an application-specific input rule beside the value it checks. In a board-game API, clients choose a sort direction and column. Because those strings feed a dynamic ordering expression, the API must validate them on the server rather than trust client-side checks. section 6.1.3 section 6.1.4

To define and use a sort-direction rule:

  • Derive SortOrderValidatorAttribute from ValidationAttribute. Give it an AllowedValues array containing ASC and DESC, and override IsValid to return ValidationResult.Success only for a nonempty allowed string. section 6.1.3
  • Return a ValidationResult with a formatted error message when the check fails. The attribute also permits a custom ErrorMessage or a different AllowedValues array at its point of use. section 6.1.3
  • Place [SortOrderValidator] on the GET action’s sortOrder parameter. A separate SortColumnValidatorAttribute accepts an entity type and checks whether the supplied name matches one of its properties. section 6.1.3
Listing 6.1 SortOrderValidatorAttribute
using System.ComponentModel.DataAnnotations;

namespace MyBGList.Attributes
{
   public class SortOrderValidatorAttribute : ValidationAttribute
   {
       public string[] AllowedValues { get; set; } = 
           new[] { "ASC", "DESC" };
       public SortOrderValidatorAttribute()
           : base("Value must be one of the following: {0}.") { }
     
       protected override ValidationResult? IsValid(
           object? value, 
           ValidationContext validationContext)
       {
           var strValue = value as string;
           if (!string.IsNullOrEmpty(strValue)
               && AllowedValues.Contains(strValue))
               return ValidationResult.Success;

           return new ValidationResult(
               FormatErrorMessage(string.Join(",", AllowedValues))
           );
       }
   }
}

The implementation shows the complete rule: allowed values, the IsValid override, a success result, and a formatted failure result. section 6.1.3

Attributes can also decorate properties on a request DTO. With [FromQuery], model binding fills those properties from the query string and validates each property. If a generic DTO needs its sort-column rule to depend on its type parameter, IValidatableObject can create and invoke the validator instead of placing that type-dependent rule directly on the property. section 6.1.5

With [ApiController], validation results enter ModelState. An invalid result produces an HTTP 400 response before the action runs. This protects the endpoint, but it does not automatically describe the custom rule to API clients: Swashbuckle documents many built-in attributes, not these custom ones. section 6.2.1 section 6.1.4

Make sorting rules visible in OpenAPI

Implement an IParameterFilter for each custom rule and register the filters with AddSwaggerGen. The filters inspect the attributes and add patterns to the generated parameter schemas. Check swagger.json for sortOrder’s ^ASC$|^DESC$ pattern and sortColumn’s property-name pattern. When validation attributes move from action parameters to DTO properties, the filter must inspect those properties too. section 6.1.4 section 6.1.5

How Building Web APIs with ASP.NET Core covers it

How deep it goes
Works through an attribute subclass, its validation result, parameter placement, and OpenAPI filters.
Examples
Uses sort-direction and sort-column validators on a GET endpoint, then moves them into a request DTO.
What it assumes
Builds on simple C# action parameters before extending validation to complex request DTOs.
What you can do after
Build it from scratch by subclassing ValidationAttribute, applying the rule to an input, and checking its error response.
How it connects
Connects model binding, request DTOs, IValidatableObject, ModelState, and OpenAPI parameter filters.

Also explained in

Compare how 3 books explain validation attribute →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Building Web APIs with ASP.NET Core. The section links point to the parts of the book it draws on.