Introducción a fluent validations en C#

En este post vamos a ver como utilizar fluent validations dentro de nuestro código y cómo pueden ayudarnos a crear nuestras aplicaciones. 

No voy a entrar a el caso en concreto de ASP.NET core 8, donde algunas de las funcionalidades que vamos a ver hoy, se pueden hacer directamente con atributos en el DTO y posiblemente con cada nueva versión veamos mas y más.

 

### indice

 

1 - Qué es fluent validations?

Fluent validation en una librería la cual nos permite definir una serie de reglas de una forma más clara y expresiva de lo que haríamos normalmente utilizando C# puro.

 

Una de las características principales de fluent validations es que cuando lees una validación estás leyendo lo que hace en inglés. Similar a como fluent assertions funciona en las aserciones de los tests.

 

 

2 - Implementar fluent validations en C#

Para implementar fluent validations lo primero que tenemos que hacer es instalar la librería correspondiente `FluentValidation`.

 

2.1 - Crear reglas en Fluent Validations

Una vez tenemos la librería lo que tenemos que hacer es crear un validador, para ello lo que hacemos es crear una clase la cual hereda de AbstractValidator<T> donde T es el tipo que queremos validar. 

En nuestro caso vamos a validar el tipo User:

public record User(string Name, string Email, int Age);

public class UserValidator : AbstractValidator<User>
{
}

Para ello en el constructor, vamos a poner las reglas que queremos indicar, en nuestro caso, que el usuario sea mayor de edad, el nombre no este vacío y el email sea un email válido:

public record User(string Name, string Email, int Age, int? AgeOfRetirement);

public class UserValidator : AbstractValidator<User>
{
    public UserValidator()
    {
        RuleFor(a => a.Age).GreaterThanOrEqualTo(18);
        RuleFor(a => a.Name).NotEmpty();
        RuleFor(a => a.Email).EmailAddress();
    }
}

 

2.2 - Combinar reglas en Fluent Validations

Fluent validation también nos permite combinar reglas, por ejemplo, imaginate que solo quieres los emails de gmail, puedes modificar la regla para que pida terminar con dicho tipo de email: 

RuleFor(a => a.Email).EmailAddress()
    .Must(e=>e.EndsWith("@gmail.com"));

En este caso ambas reglas son obligatorias, un email válido, y que termine en @gmail.com.

 

2.3 - Personalizar errores en fluent validations

Cuando ejecutemos nuestras validaciones vamos a comprobar las reglas y estas nos dan unos mensajes, códigos de errores, etc, esto se puede configurar, por ejemplo, vamos a ser más específicos con el error del email y vamos a indicar que el usuario tiene que usar un gmail:

RuleFor(a => a.Email).EmailAddress()
	.Must(e=>e.EndsWith("@gmail.com"))
    .WithMessage("Debes utilizar un correo de gmail.");

 

2.4 - Fluent Validations para validaciones condicionales

Uno de los casos más comunes es querer condicionar cierta validación, si un atributo es X validar Y si no ignorarlo o validar z, eso es lo que vamos a poner aquí, vamos a comprobar que el año de jubilación para todos lo mayores de 65, y además vamos a comprobar que si se es menor de 65, dicho valor debe ser nulo. 

When(a => a.Age >= 65, () =>
        RuleFor(user => user.AgeOfRetirement).NotNull().GreaterThanOrEqualTo(65)
    )
    .Otherwise(() => RuleFor(user => user.AgeOfRetirement).Null());

Ya se que en el mundo real no es tan fácil, pero para hacernos una idea, nos sirve. 

 

3 - Integrar Fluent Validations en ASP.NET Core

Ahora que hemos visto unos cuantos casos de usos, vamos a ver cómo integrarlo en nuestras aplicaciones.

Lo primero que debemos hacer es introducir nuestra validación al contenedor de dependencias.

builder.Services.AddScoped<IValidator<User>, UserValidator>();

Y ahora tenemos dos formas de utilizarla.

 

3.1 - Validaciones manuales con fluent assertions

La primera es, inyectamos la interfaz IValidator<User> y la utilizamos donde la necesitemos y directamente invocando el método `validate` o `ValidateAsync` cuando podamos: 

app.MapPost("/user", async (User user, IValidator<User> validator) =>
    {
        var validationResult = await validator.ValidateAsync(user);

        if (!validationResult.IsValid)
        {
            return string.Join(',', validationResult.Errors.Select(a => a.ErrorMessage));
        }

        return $"User created (simulated) {user.Name}";
    })
    .WithOpenApi();

Si enviamos el siguiente payload, vemos que tanto el email como la edad/edad de retiro no cuadran con lo que necesitamos, así que nos debería dar varios errores: 

{
  "name": "netmentor",
  "email": "[email protected]",
  "age": 65,
  "ageOfRetirement": null
}

Resultado: 

resultado fluent validations

 

3.2 - Validaciones automáticas con fluent assertions

Esta parte es un poco legacy, de hecho desde la aplicacion oficial no la recomiendan más, así que en vez de enseñar un ejemplo, simplemente voy a mencionar que hay un paquete llamado fluentvalidation.aspnetcore que incluye las validaciones en la request pipeline.

 

hay una librería llamada SharpGrip.FluentValidation.AutoValidation que hace una funcionalidad similar a la mencionada de la request pipeline.

Personalmente, no soy el mejor amigo de la magia, así que tener la validación como un paso en el código es mi opción preferencial.  (el punto 3.1).

 


Uso del bloqueador de anuncios adblock

Hola!

Primero de todo bienvenido a la web de NetMentor donde podrás aprender programación en C# y .NET desde un nivel de principiante hasta más avanzado.


Yo entiendo que utilices un bloqueador de anuncios como AdBlock, Ublock o el propio navegador Brave. Pero te tengo que pedir por favor que desactives el bloqueador para esta web.


Intento personalmente no poner mucha publicidad, la justa para pagar el servidor y por supuesto que no sea intrusiva; Si pese a ello piensas que es intrusiva siempre me puedes escribir por privado o por Twitter a @NetMentorTW.


Si ya lo has desactivado, por favor recarga la página.


Un saludo y muchas gracias por tu colaboración

© copyright 2024 NetMentor | Todos los derechos reservados | RSS Feed

Buy me a coffee Invitame a un café