This image was taken from: https://github.com/FluentValidation/FluentValidation.AspNetCore

Model validations— Dotnet 6

Oscar Chávez

--

Everyone knows that it is necessary to validate the data sent by the client, but there are many options to do it. In this article, we use the Fluent Validation Nuget Package.

We use two packages, they are these:

FluentValidation: To do validation by model class. Click here

FluentValidation.AspNetCore: To define FluentValidation instead of ASP.NET model validations. Click here

If you want to get more documents, you can read the official documents here.

Let’s do this!!!

First, we add packages to our project.

Then, we can start with model and validations.

We use this model:

It’s time to create a validation class, we inherit from the Fluent.Validation interface AbstractValidator<T> here and assign that the generic to validate is our User model. Also, we add the constructor.

Now, we can add our validations. For example, we need the UserName prop to be:
1. It is not empty
2. Do not be null,
3. Have a minimum and maximum length.
Well… we do this:

For Email prop you can use the same validation as NotEmpty and NotNull. But we can use another validation: EmailAddress(). It would be something like this:

And, for ConfirmEmail prop, we do the same thing, but add another validation: When() or WhenAsync(). This validation helps us compare model props.

With Phones list prop, we add another validation: Must() or MustAsync(). This helps us add custom logic inside the validation and use ValidationContext<T> to throw failures.

In this example, we check if any items within the Phone list are null or empty. If everything is ok it returns true, if not it adds a failure to the ValdiationContext.

To finish (but that’s not to say that’s all) we have LessThan() or LessThanOrEqualTo() and GreaterThan() or GreaterThanOrEqualTo(). The name says it all, right?

So far, we know how to do validations and return failures, but how does this work. Well, let’s check it out.

Let’s start with RulesFor(x => x.PropName). In simple words, this method gives us access to specific props within the model we validate. For example, we want to add validation to the UserName property, we just do this:

Now, we want this prop to be required in the json body sent by the client. Well, we set it to NotNull:

As you can see, NotNull is followed by the .WithMessage() method. This helps us to return a failure or error when validation of the parent (in this case, NotNull) fails. We can use this method with all validations.

What do we see if we send a json body without the username? Well, we see this:

Good, validation works. Let;s add NotEmpty validation.

Now, we check if the UserName property sent by the client is not empty. BadRequest message look like:

Time to talk about CascadeMode. In just a validation interrupt option, we have 2 options: CascadeMode.Continue or CascadeMode.Stop. To explain this, we send a json body with no username key and obviously no value, and check the BadRequest message.

With CascadeMode.Continue:

With CascadeMode.Stop:

As you can see, CascadeMode.Continue returns all errors. On the other hand, CascadeMode.Stop simply returns the first error, ignoring the others.

I personally use CascadeMode.Continue as it returns all errors and is known to the client in the frontend or mobile app.

The other validations work the same as these. And the name of the method says what it does (remember the example with .LessOrEqualThan(), …)

Now, just need add FluentValidation into our Program.cs file. We do this:

And that’s it. We configure our API to ignore default validations and use custom validations using FluentValidation.

I hope you liked this article. See you in the next one.

--

--

Oscar Chávez

I’m a software developer with experience developing web applications (APIs and microservices) using .NET and ReactJS, I also have experience with Flutter.