Use custom validation responses with fluent validation

RajGan picture RajGan · Aug 18, 2017 · Viewed 16.4k times · Source

Hello I am trying to get custom validation response for my webApi using .NET Core.

Here I want to have response model like

[{
  ErrorCode:
  ErrorField:
  ErrorMsg:
}]

I have a validator class and currently we just check ModalState.IsValid for validation Error and pass on the modelstate object as BadRequest.

But new requirement wants us to have ErrorCodes for each validation failure.

My sample Validator Class

public class TestModelValidator :  AbstractValidator<TestModel>{

public TestModelValidator {
   RuleFor(x=> x.Name).NotEmpty().WithErrorCode("1001");
   RuleFor(x=> x.Age).NotEmpty().WithErrorCode("1002");
  }
}

I can use something similar in my actions to get validation result

Opt1:

 var validator = new TestModelValidator();
    var result = validator.Validate(inputObj);
    var errorList = result.Error;

and manipulate ValidationResult to my customn Response object. or
Opt2:

I can use [CustomizeValidator] attribute and maybe an Interceptors.

but for Opt2 I don't know how to retrieve ValidationResult from interceptor to controller action.

All I want is to write a common method so that I avoid calling Opt1 in every controller action method for validation.

Request to point me to correct resource.

Answer

asd picture asd · Dec 11, 2018

try with this:

services.Configure<ApiBehaviorOptions>(options =>
{
    options.SuppressModelStateInvalidFilter = true;
});

I validate the model with fluentvalidation, after build the BadResquest response in a ActionFilter class:

public class ValidateModelStateAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (!context.ModelState.IsValid)
        {
            var errors = context.ModelState.Values.Where(v => v.Errors.Count > 0)
                    .SelectMany(v => v.Errors)
                    .Select(v => v.ErrorMessage)
                    .ToList();

            var responseObj = new
            {
                Message = "Bad Request",
                Errors = errors                    
            };

            context.Result = new JsonResult(responseObj)
            {
                StatusCode = 400
            };
        }
    }
}

In StartUp.cs:

        services.AddMvc(options =>
        {
            options.Filters.Add(typeof(ValidateModelStateAttribute));
        })
        .AddFluentValidation(fvc => fvc.RegisterValidatorsFromAssemblyContaining<Startup>());

        services.Configure<ApiBehaviorOptions>(options =>
        {
            options.SuppressModelStateInvalidFilter = true;
        });

And it works fine. I hope you find it useful