Skip to content

MediatR Integration

Casey edited this page Apr 6, 2025 · 3 revisions

EntityAxis includes first-class support for MediatR, enabling clean and composable command/query processing using the CQRS pattern.

This guide shows you how to register and use MediatR handlers provided by EntityAxis.


βš™οΈ Registering Handlers and Validators

You can register all generic command/query handlers and their validators using the fluent extension method:

// Option 1: Use the simplified registration method
services.AddEntityAxisHandlers<ProductCreateModel, ProductUpdateModel, Product, Guid>();

// Option 2: Use the builder pattern for more control
services.AddEntityAxisCommandHandlers<Product, Guid>(builder =>
{
    builder.AddCreate<ProductCreateModel>();
    builder.AddUpdate<ProductUpdateModel>();
    builder.AddDelete();
});

services.AddEntityAxisQueryHandlers<Product, Guid>(builder =>
{
    builder.AddGetById();
    builder.AddGetAll();
    builder.AddGetPaged();
});

This will register handlers for:

  • CreateEntityCommand<TModel, TEntity, TKey>
  • UpdateEntityCommand<TModel, TEntity, TKey>
  • DeleteEntityCommand<TEntity, TKey>
  • GetByIdQuery<TEntity, TKey>
  • GetAllQuery<TEntity, TKey>
  • GetPagedQuery<TEntity, TKey>

πŸ’‘ These handlers rely on services like ICreate, IUpdate, IDelete, and IQueryService. Make sure they are registered, typically using the AddEntityAxisCommandService and AddEntityAxisQueryService extensions.


πŸ” Setting Up AutoMapper

EntityAxis uses AutoMapper internally in its handlers to map between your models and domain entities. You must register your mappings during startup.

Example:

public class ProductProfile : Profile
{
    public ProductProfile()
    {
        CreateMap<ProductCreateModel, Product>();
        CreateMap<ProductUpdateModel, Product>();
    }
}

Then register your profile like this:

services.AddAutoMapper(typeof(ProductProfile).Assembly);

πŸ” Request Validation

EntityAxis provides validators for its built-in commands and queries using FluentValidation.

To enable request validation with MediatR, add this pipeline behavior:

services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestValidationBehavior<,>));

This ensures that commands like CreateEntityCommand and UpdateEntityCommand are validated before reaching their handlers.

πŸ“¦ The RequestValidationBehavior<,> class is included in the sample app, but consumers must define it themselves or reuse a shared version across projects.


✍️ Custom Create/Update Validators

You can define model-specific validators to ensure your create/update models meet your domain requirements.

Example:

public class ProductCreateModelValidator : AbstractValidator<ProductCreateModel>
{
    public ProductCreateModelValidator()
    {
        RuleFor(p => p.Name)
            .NotEmpty().WithMessage("Product name is required.")
            .MaximumLength(100);
    }
}

Then register them via:

services.AddValidatorsFromAssemblyContaining<ProductCreateModelValidator>();

EntityAxis will automatically resolve and invoke these validators when processing commands.


πŸš€ Triggering Handlers with IMediator

Once everything is wired up, you can use MediatR like this:

// Option 1: Send the generic command directly
var command = new CreateEntityCommand<ProductCreateModel, Product, Guid>(new ProductCreateModel
{
    Name = "Desk",
    Description = "A modern desk"
});

var productId = await mediator.Send(command);

// Option 2: Define a well-named use case class and send that
public class CreateProductCommand
    : CreateEntityCommand<ProductCreateModel, Product, Guid>
{
    public CreateProductCommand(ProductCreateModel model) : base(model) { }
}

// Usage
var customCommand = new CreateProductCommand(new ProductCreateModel
{
    Name = "Chair",
    Description = "An ergonomic chair"
});

var newId = await mediator.Send(customCommand);

This sends a CreateEntityCommand and returns the ID of the newly created entity.


πŸ“š See Also

Clone this wiki locally