Ensuring Data Quality with Command Handler Validators

In the realm of software development, ensuring the quality of the data you're handling is paramount. With the rise of Microservices, CQRS (Command Query Responsibility Segregation) and Mediator patterns, developers now, more than ever, need a reliable mechanism to validate data before processing it. Enter Command Handler Validators - a mechanism to validate command objects before they're handled.

In this blog post, we'll discuss how to implement a Command Handler Validator using MediatR, FluentValidation, and ASP.NET Core.


A Practical Example

Consider the following code for creating a new customer:

 public class CreateCustomerCommand : IRequest
 {
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
 } 
The CreateCustomerCommand command is then handled by CreateCustomerCommandHandler:
 public class CreateCustomerCommandHandler : IRequestHandler
 {
    public async Task Handle(CreateCustomerCommand request, CancellationToken cancellationToken)
    {
        return await Task.FromResult(new Customer
        {
            FirstName = request.FirstName,
            LastName = request.LastName,
            Email = request.Email
        });
    }
 }
 
So far, so good. However, before the CreateCustomerCommandHandler processes the command, we need to ensure that the data is valid. This is where the Command Handler Validator comes in. Implementing the Validator The validation logic is implemented using FluentValidation, a popular .NET library for building strongly-typed validation rules. Our CreateCustomerCommandValidator looks like this:
 public class CreateCustomerCommandValidator : AbstractValidator
 {
    public CreateCustomerCommandValidator()
    {
        RuleFor(x => x.FirstName).NotEmpty().WithMessage("First name is required");
        RuleFor(x => x.LastName).NotEmpty().WithMessage("Last name is required");
        RuleFor(x => x.Email).NotEmpty().EmailAddress().WithMessage("A valid email is required");
    }
 }
This validator ensures that FirstName, LastName, and Email are not empty, and that Email is in a valid format. Wiring it Up in the Application To use our validator, we need to register it in the application's service collection. This is done in the ConfigureServices method in the Startup class:
 public void ConfigureServices(IServiceCollection services)
 {
    services.AddControllers()
        .AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining());
    
    services.AddMediatR(typeof(Startup).Assembly);
    
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
    });
 }
The AddFluentValidation method scans the assembly that contains CreateCustomerCommandValidator and automatically registers all validators it finds. Conclusion Command Handler Validators are a powerful tool to ensure that your data is valid before it's processed. They help to maintain the integrity of your data, and can prevent many common bugs that could occur due to invalid data. By implementing them using FluentValidation and MediatR, we can take advantage of the strong typing, easy testability, and maintainability these libraries provide. So, the next time you find yourself needing to validate data before processing it, consider using a Command Handler Validator.

Comments

Popular posts from this blog

Enhancing Functionality with the Decorator Pattern in .NET

Supercharge Your Unit Testing with MOQ, Dependency Injection, and Fluent Assertions