ASP.NET Core 2.2 & 3 REST API #21 — Validating requests with FluentValidation

Theodoros Ntakouris
3 min readJul 30, 2019

--

Up Next: Extended Swagger Documentation

We’re going to see how we are going to validate incoming requests. First, we are going to use the standard way — without using any other package and secondly, we are going to explain why FluentValidation is a better approach.

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
  • 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

Code is available on Github and the instructional videos are located on YouTube.

Keep Coding

--

--

No responses yet