ASP.NET Core ModelState Validation Filter
During my code review sessions I see a lot of duplicate for the ModelState validation like
public async Task<IActionResult> AddAsync(PersonAddSubmitModel model)
{
if(ModelState.IsValid)
{
return BadRequest(ModelState);
}
// ......
}
But it makes no sense to use the same code in every action to validate your submit model. It can be easier!
Validation Filter
public class ModelStateValidationAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
context.Result = new BadRequestObjectResult(context.ModelState);
}
}
}
With this attribute you can save a lot of redudant code:
[ModelStateValidation]
public async Task<IActionResult> AddAsync(PersonAddSubmitModel model)
{
// ......
}
Pro Tip: Use IValidatableObject
I am not a big fan of the DataAnnotation
attributes.
But I really like IValidatableObject
because it also gives you a context with the posibility to not only validate some plain input texts, you also can access o your dependency injected services and validate against logic or your database.
ASP.NET Core automatically validates all input models if they implement IValidatableObject
.
public abstract class BaseSubmitModel : IValidatableObject
{
public abstract IEnumerable<ValidationResult> Validate(ValidationContext validationContext);
}
public class PersonAddSubmitModel : BaseSubmitModel
{
public string Name {get;set;}
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext);
{
if(string.IsNullOrWhiteSpace(Name)) yield return new ValidationResult($"{nameof(Name)} is missing.", new [] {nameof(Name)})
}
}