ASP.NET Core 2.2 & 3 REST API #21 — Validating requests with FluentValidation
By: Theodoros Ntakouris
Tags: Software Engineering, Microsoft, Csharp, Aspnetcore, Rest Api

In our CreateTag endpoint, we receive a CreateTagRequest . Let’s demonstrate some validation by doing 2 checks on the tag:

Should not be empty

Should only contain alphanumeric characters

If you were to do this in the controller, you’d just have these few lines of code, in your controller:

Obviously, this is not maintainable. For even the slightest change or addition you’d have to alter and review each and every controller method that has to do with tags? Does that mindset ring a bell?

Furthermore, .NET supports validation via attributes. For example you can add a [Email] attribute to a contract and then just check if(!ModelState.IsValid) , translating the model state error to an api response error.

But then, you’d have to:

Store all the validation logic on our Contracts , which violates the Single Responsibility Principles

FluentValidation

That’s the clean way to do this.

Do not confuse contract/request validation with business logic validation

Add FluentValidation.AspNetCore

Go to the MvcInstaller , on our .AddMvc() chain .AddFluentValidation

, on our chain Fill in automatic registrations of everything contained in our assembly, like the previous auto mapper tutorial by: (mvcConfiguration => mvcConfiguration.RegisterValidatorsFromAssemblyContaining<Startup>()) . This should find everything that contains the AbstractValidator class.

Let’s create a new folder, Validators . We’re going to follow the naming convention XRequestValidator (where XRequest is the contract name).

Create the CreateTagRequestValidator : AbstractValidator<CreateTagRequest> and let’s get started. Things are pretty straightforward:

Add a consturctor

Add rules

This means, that this validation is automatically going to be applied here.

The next step would be to not have to map errors between the FluentValidation and the Contract layer.

First, we are going to create some new contracts:

ErrorModel

ErrorResponse (returns a list of ErrorModel )

Next step would be to create a filter:

Filters/ ValidationFilter : IAsyncActionFilter . A filter is essentially middleware. Very briefly, a middleware is a tiny step on our request pipeline.

request -> step1 -> step2 -> ... -> controller -> ... -> step2 -> step1 -> response .

For example:

Authentication is one middleware

Logging is one middleware (you can see printing in the dev console)

Model State validation is one middleware

In fact, the ActionExecutionDelegate next is the controller ‘step’ when you create your own middleware.

In the context of this filter, model state validations have already been applied. This means, that we can just intercept this invalid state and return the ErrorResponse to the user.

Take a moment to read through the following code. It’s not complex and pretty self explanatory.

Last step would be to register the filter in our Mvc pipeline.

.AddMvc(options => ... options.Filters.Add<ValidationFilter>(); ...);

That’s it

Tip: For custom validation logic use the .Must() method.

Up Next: Extended Swagger Documentation