Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Core Web API Validation Error Handling

I'm trying to return a custom response object when a model fails validation in my Web API project. I have attached attributes to the model like this:

  public class DateLessThanAttribute : ValidationAttribute
  {
    private readonly string _comparisonProperty;

    public DateLessThanAttribute(string comparisonProperty)
    {
      _comparisonProperty = comparisonProperty;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
      ErrorMessage = ErrorMessageString;
      var currentValue = (DateTime)value;

      var property = validationContext.ObjectType.GetProperty(_comparisonProperty);

      if (property == null)
        throw new ArgumentException("Property with this name not found");

      var comparisonValue = (DateTime)property.GetValue(validationContext.ObjectInstance);

      if (currentValue > comparisonValue)
        return new ValidationResult(ErrorMessage);

      return ValidationResult.Success;
    }
  }

On the model:

[DateLessThan("EndDate", ErrorMessage = "StartDate must be less than EndDate")]
public DateTime StartDate { get; set; }

And the controller:

public void PostCostingStandard(CostStandardRequest request)
{
  CostResult costResult;
  if (ModelState.IsValid)
  {
    // work
  }
  else
  {
    // return bad costResult object
  }
}

However, the model never reaches inside the controller to hit ModelState.IsValid. I've tried creating an ActionFilterAttribute and attaching it to my controller action as outlined here, but when setting a breakpoint, the ActionFilterAttribute never runs because the DateLessThanAttribute returns a response first. Is there an order to these filters that I've missed or have I simply implemented something incorrectly?

like image 878
Ben Avatar asked Nov 06 '18 17:11

Ben


1 Answers

You have to disable automatic model state validation. You can do so by adding the following code to your startup.cs

services.Configure<ApiBehaviorOptions>(options =>
{
    options.SuppressModelStateInvalidFilter = true;
});
like image 99
Danijel Avatar answered Sep 26 '22 02:09

Danijel