redar ismail
redar ismail

Reputation: 171

Fluent Validation and ASP.NET Core 6 Web API

After following the FluentValidation website, I was able to successfully implement Fluent Validation.

However, my response body looks very different and contains a lot of information. Is it possible to have a regular response body with validation errors?

I will put down the steps I took to implement Fluent Validation. Your advice and help are much appreciated. I am using Manual Validation because based on the Fluent Validation website they are not supporting the Automatic Validation anymore.

In the Program file, I added:

builder.Services.AddValidatorsFromAssemblyContaining<CityValidator>();

Then I added a class that validated my City class which has two properties Name and Description :

public class CityValidator : AbstractValidator<City>
{
    public CityValidator()
    {
        RuleFor(x => x.Name)
                .NotNull()
                .NotEmpty()
                .WithMessage("Please specify a name");
        RuleFor(x => x.Description)
                .NotNull()
                .NotEmpty()
                .WithMessage("Please specify a Description");
    }
}

In my CitiesController constructor I injected Validator<City> validator and in my Action method, I am using this code:

ValidationResult result = await _validator.ValidateAsync(city);

if (!result.IsValid)
{
    result.AddToModelState(this.ModelState);
    return BadRequest(result);
}

The AddToModelState is an extension method:

public static void AddToModelState(this ValidationResult result, ModelStateDictionary modelState)
{
    if (!result.IsValid)
    {
        foreach (var error in result.Errors)
        {
            modelState.AddModelError(error.PropertyName, error.ErrorMessage);
        }
    }
}

On POST, I am getting the response as:

{
    "isValid": false,
    "errors": [
        {
            "propertyName": "Name",
            "errorMessage": "Please specify a name",
            "attemptedValue": "",
            "customState": null,
            "severity": 0,
            "errorCode": "NotEmptyValidator",
            "formattedMessagePlaceholderValues": {
                "PropertyName": "Name",
                "PropertyValue": ""
            }
        },
        {
            "propertyName": "Description",
            "errorMessage": "Please specify a name",
            "attemptedValue": "",
            "customState": null,
            "severity": 0,
            "errorCode": "NotEmptyValidator",
            "formattedMessagePlaceholderValues": {
                "PropertyName": "Description",
                "PropertyValue": ""
            }
        }
    ],
    "ruleSetsExecuted": [
        "default"
    ]
}

While the regular response without Fluent Validation looks like this:

{
    "errors": {
        "": [
            "A non-empty request body is required."
        ],
        "pointofInterest": [
            "The pointofInterest field is required."
        ]
    },
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
    "title": "One or more validation errors occurred.",
    "status": 400,
    "traceId": "00-1a68c87bda2ffb8de50b7d2888b32d02-94d30c7679aec10b-00"
}

The question: Is there a way to use Fluent Validation and get the response format like:

{
    "errors": {
        "": [
            "A non-empty request body is required."
        ],
        "pointofInterest": [
            "The pointofInterest field is required."
        ]
    },
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
    "title": "One or more validation errors occurred.",
    "status": 400,
    "traceId": "00-1a68c87bda2ffb8de50b7d2888b32d02-94d30c7679aec10b-00"
}

Upvotes: 2

Views: 3845

Answers (2)

yingyong yu
yingyong yu

Reputation: 1

 if(!result.IsValid)
{
        result.AddToModelState(this.ModelState);
        return ValidationProblem(ModelState);
}

Errors

Upvotes: 0

CodingMytra
CodingMytra

Reputation: 2600

Updated ans:

with your code, you can simply replace.

 return BadRequest(result); // replace this line with below line.
 return ValidationProblem(ModelState);

then you get same format as required.

enter image description here

------------------------*----------------------------------------

Please ignore this for manual validation.

You don't need explicit validation call.

this code is not required:

ValidationResult result = await _validator.ValidateAsync(city);

if (!result.IsValid)
{
    result.AddToModelState(this.ModelState);
    return BadRequest(result);
}

it will auto validate the model using your custom validator.

you simply need this

if (!ModelState.IsValid)
{
   return BadRequest(ModelState);
}

and it will give you errors in the require format.

Upvotes: 2

Related Questions