.NET Core WebAPI Validation with FluentValidation and Swagger

Hi there, there are a lot of ways to add validation to your models when you are building a REST API and you want to add validation (max length, regular expression, required, etc) to your DTO models, but if you want to mantain your DTO models as POCO, in my opinion you should use Fluent Validation; in this post we are going to try to explain how to configure Fluent Validation in your project.


  1. Create a new folder "Validators" in your project to organize all your validators in the same place. Use namespaces to organize this folder. 
  2. Install the last version of the nuget FluentValidation
  3. Inside this new folder create a new class like this:
  4. using Core.DTO.Security;
    using Core.Interfaces.Security;
    using FluentValidation;
    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace Core.Validators.Security
    {
        public class UserDTOValidator : AbstractValidator
        {
            private readonly ISecurityService _securityService;
            public UserDTOValidator(ISecurityService securityService)
            {
                _securityService = securityService;
                RuleFor(x => x.UserReference).NotEmpty();
                RuleFor(x => x.UserReference).MaximumLength(100);
                RuleFor(x => x.Name).MaximumLength(100);
                RuleFor(x => x.Name).NotEmpty();
                RuleFor(x => x.Email).NotEmpty();
                RuleFor(x => x.Email).Matches(@"^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$");
                RuleFor(x => x.Email).MustAsync(IsEmailAlreadyInDatabase);
            }
    
            private async Task IsEmailAlreadyInDatabase(string abbreviation, CancellationToken token)
            {
                var user = await _securityService.GetUserByEmail(abbreviation);
                return user != null;
            }
        }
    }
    In my case I use the next nomenclature:<NameOfTheClass>Validator.cs. Names are very important, we need to explain the content of our class to our readers.
  5. In the ConfigureServices method, tag a call to AddFluentValidation onto the AddMvc method.
  6.             //Fluent Validation
                services.AddMvc()
               .AddFluentValidation(o =>
               {
                   o.RegisterValidatorsFromAssemblyContaining();
               });
    
  7. Register FluentValidation in Swagger. To do that, we'll need to add the MicroElements.Swashbuckle.FluentValidation NuGet package and modify the AddSwaggerGent like this:
  8.             // Register the Swagger generator, defining 1 or more Swagger documents
                services.AddSwaggerGen(c =>
                {
                    c.SwaggerDoc("v1", new OpenApiInfo
                    {
                        Version = "v1",
                        Title = "WhiteLabel API",
                        Description = "WhiteLabel ASP.NET Core Web API",
                        TermsOfService = new Uri("https://www.yourwebsite.com/termsandservice")
                    });
                    c.AddSecurityDefinition("basic", new OpenApiSecurityScheme
                    {
                        Name = "Authorization",
                        Type = SecuritySchemeType.Http,
                        Scheme = "basic",
                        In = ParameterLocation.Header,
                        Description = "Basic Authorization header using the Bearer scheme."
                    });
                    c.DocumentFilter();
                    c.AddFluentValidationRules();
                });
    
    This single line of code (c.AddFluentValidationRules())will let swagger check your validator classes to show the data annotations documentation. Then, when you run your project, you will be able to see a schema like this in Swagger: 

  9. Add the validation in your endpoint:
  10.         [HttpPost, Route("users")]
            public async Task AddUser([FromBody] UserDTO user)
            {
                Guard.Requires(user, nameof(user)).IsNotNull();
                if (ModelState.IsValid)
                {
                    return Ok(await _securityService.AddUser(_mapper.Map(user)));
                }
                
                return BadRequest(ModelState);
            }
    
You can see the whole code here https://github.com/racsus/WhiteLabelAPI
And you can find more details about this WhiteLabel Web API project here https://oscarchelo.blogspot.com/2020/04/net-core-31-whilelabel-web-api-project.html

References

https://www.anexinet.com/blog/asp-net-core-fluentvalidation-swagger/

https://oscarchelo.blogspot.com/2020/04/net-core-31-whilelabel-web-api-project.html
     


Comentarios