SchwabenCode Blog Post

ASP.NET Core ModelState Validation Filter

During my code review sessions I see a lot of duplicate for the ModelState validation like

1public async Task<IActionResult> AddAsync(PersonAddSubmitModel model)
2{
3    if(ModelState.IsValid)
4    {
5        return BadRequest(ModelState);
6    }
7
8    // ......
9}

But it makes no sense to use the same code in every action to validate your submit model. It can be easier!

Validation Filter

 1
 2    public class ModelStateValidationAttribute : ActionFilterAttribute
 3    {
 4        public override void OnActionExecuting(ActionExecutingContext context)
 5        {
 6            if (!context.ModelState.IsValid)
 7            {
 8                context.Result = new BadRequestObjectResult(context.ModelState);
 9            }
10        }
11    }

With this attribute you can save a lot of redudant code:

1[ModelStateValidation]
2public async Task<IActionResult> AddAsync(PersonAddSubmitModel model)
3{
4    // ......
5}

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.

 1public abstract class BaseSubmitModel : IValidatableObject
 2{
 3    public abstract IEnumerable<ValidationResult> Validate(ValidationContext validationContext);
 4}
 5
 6public class PersonAddSubmitModel : BaseSubmitModel
 7{
 8    public string Name {get;set;}
 9
10    public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext);
11    {
12        if(string.IsNullOrWhiteSpace(Name)) yield return new ValidationResult($"{nameof(Name)} is missing.", new [] {nameof(Name)})
13    }
14}

Comments

Twitter Facebook LinkedIn WhatsApp