Documentation Index Fetch the complete documentation index at: https://mintlify.com/IntentArchitect/Intent.Modules.NET/llms.txt
Use this file to discover all available pages before exploring further.
The Intent.AspNetCore.Controllers.Dispatch.MediatR module instructs ASP.NET Core Controllers to dispatch Commands and Queries to separate handlers via MediatR, implementing the CQRS pattern in your Web API.
Overview
This module bridges ASP.NET Core Controllers with the MediatR library, enabling a clean separation between your HTTP layer and application logic. Controllers become thin dispatchers that forward requests to specialized command and query handlers.
Architecture
The module implements a clean CQRS architecture:
What Gets Generated
Controllers are generated with MediatR injection:
[ ApiController ]
[ Route ( "api/orders" )]
public class OrdersController : ControllerBase
{
private readonly ISender _mediator ;
public OrdersController ( ISender mediator )
{
_mediator = mediator ;
}
[ HttpGet ( "{id}" )]
[ ProducesResponseType ( typeof ( OrderDto ), StatusCodes . Status200OK )]
[ ProducesResponseType ( StatusCodes . Status404NotFound )]
public async Task < ActionResult < OrderDto >> GetById (
[ FromRoute ] Guid id ,
CancellationToken cancellationToken )
{
var result = await _mediator . Send (
new GetOrderByIdQuery { Id = id },
cancellationToken );
return result != null ? Ok ( result ) : NotFound ();
}
[ HttpPost ]
[ ProducesResponseType ( typeof ( Guid ), StatusCodes . Status201Created )]
[ ProducesResponseType ( StatusCodes . Status400BadRequest )]
public async Task < ActionResult < Guid >> Create (
[ FromBody ] CreateOrderCommand command ,
CancellationToken cancellationToken )
{
var orderId = await _mediator . Send ( command , cancellationToken );
return CreatedAtAction ( nameof ( GetById ), new { id = orderId }, orderId );
}
[ HttpPut ( "{id}" )]
[ ProducesResponseType ( StatusCodes . Status204NoContent )]
[ ProducesResponseType ( StatusCodes . Status400BadRequest )]
[ ProducesResponseType ( StatusCodes . Status404NotFound )]
public async Task < ActionResult > Update (
[ FromRoute ] Guid id ,
[ FromBody ] UpdateOrderCommand command ,
CancellationToken cancellationToken )
{
if ( command . Id != id )
return BadRequest ();
await _mediator . Send ( command , cancellationToken );
return NoContent ();
}
[ HttpDelete ( "{id}" )]
[ ProducesResponseType ( StatusCodes . Status204NoContent )]
[ ProducesResponseType ( StatusCodes . Status404NotFound )]
public async Task < ActionResult > Delete (
[ FromRoute ] Guid id ,
CancellationToken cancellationToken )
{
await _mediator . Send ( new DeleteOrderCommand { Id = id }, cancellationToken );
return NoContent ();
}
}
Key Features
CQRS Pattern Separates read and write operations using Commands and Queries
Thin Controllers Controllers focus on HTTP concerns, not business logic
MediatR Integration Leverages MediatR’s request/response pipeline
Pipeline Behaviors Supports validation, logging, and other cross-cutting concerns
Commands vs Queries
Commands
Commands represent write operations that modify state:
public class CreateOrderCommand : IRequest < Guid >
{
public Guid CustomerId { get ; set ; }
public List < OrderItemDto > Items { get ; set ; }
}
public class CreateOrderCommandHandler : IRequestHandler < CreateOrderCommand , Guid >
{
private readonly IApplicationDbContext _dbContext ;
public CreateOrderCommandHandler ( IApplicationDbContext dbContext )
{
_dbContext = dbContext ;
}
public async Task < Guid > Handle (
CreateOrderCommand request ,
CancellationToken cancellationToken )
{
var order = new Order
{
CustomerId = request . CustomerId ,
// Map properties...
};
_dbContext . Orders . Add ( order );
await _dbContext . SaveChangesAsync ( cancellationToken );
return order . Id ;
}
}
Queries
Queries represent read operations that don’t modify state:
public class GetOrderByIdQuery : IRequest < OrderDto >
{
public Guid Id { get ; set ; }
}
public class GetOrderByIdQueryHandler : IRequestHandler < GetOrderByIdQuery , OrderDto >
{
private readonly IApplicationDbContext _dbContext ;
private readonly IMapper _mapper ;
public GetOrderByIdQueryHandler (
IApplicationDbContext dbContext ,
IMapper mapper )
{
_dbContext = dbContext ;
_mapper = mapper ;
}
public async Task < OrderDto > Handle (
GetOrderByIdQuery request ,
CancellationToken cancellationToken )
{
var order = await _dbContext . Orders
. Include ( x => x . Items )
. FirstOrDefaultAsync ( x => x . Id == request . Id , cancellationToken );
return _mapper . Map < OrderDto >( order );
}
}
Benefits
Separation of Concerns
Controller Responsibilities
HTTP request/response handling
Route configuration
Parameter binding
Status code determination
Business logic
Data access
Domain operations
Validation
Testability
Handlers can be tested independently of HTTP concerns:
[ Fact ]
public async Task CreateOrder_ValidCommand_ReturnsOrderId ()
{
// Arrange
var dbContext = CreateInMemoryDbContext ();
var handler = new CreateOrderCommandHandler ( dbContext );
var command = new CreateOrderCommand
{
CustomerId = Guid . NewGuid (),
Items = new List < OrderItemDto > { /* ... */ }
};
// Act
var result = await handler . Handle ( command , CancellationToken . None );
// Assert
Assert . NotEqual ( Guid . Empty , result );
var order = await dbContext . Orders . FindAsync ( result );
Assert . NotNull ( order );
}
Pipeline Behaviors
MediatR supports pipeline behaviors for cross-cutting concerns:
Validation Behavior
public class ValidationBehavior < TRequest , TResponse >
: IPipelineBehavior < TRequest , TResponse >
where TRequest : IRequest < TResponse >
{
private readonly IEnumerable < IValidator < TRequest >> _validators ;
public ValidationBehavior ( IEnumerable < IValidator < TRequest >> validators )
{
_validators = validators ;
}
public async Task < TResponse > Handle (
TRequest request ,
RequestHandlerDelegate < TResponse > next ,
CancellationToken cancellationToken )
{
if ( _validators . Any ())
{
var context = new ValidationContext < TRequest >( request );
var results = await Task . WhenAll (
_validators . Select ( v => v . ValidateAsync ( context , cancellationToken )));
var failures = results
. SelectMany ( r => r . Errors )
. Where ( f => f != null )
. ToList ();
if ( failures . Any ())
throw new ValidationException ( failures );
}
return await next ();
}
}
Logging Behavior
public class LoggingBehavior < TRequest , TResponse >
: IPipelineBehavior < TRequest , TResponse >
where TRequest : IRequest < TResponse >
{
private readonly ILogger < LoggingBehavior < TRequest , TResponse >> _logger ;
public LoggingBehavior ( ILogger < LoggingBehavior < TRequest , TResponse >> logger )
{
_logger = logger ;
}
public async Task < TResponse > Handle (
TRequest request ,
RequestHandlerDelegate < TResponse > next ,
CancellationToken cancellationToken )
{
_logger . LogInformation (
"Handling {RequestName}" ,
typeof ( TRequest ). Name );
var response = await next ();
_logger . LogInformation (
"Handled {RequestName}" ,
typeof ( TRequest ). Name );
return response ;
}
}
Services Designer Configuration
In the Services Designer, operations are automatically mapped to Commands or Queries:
Create Service
Add a service in the Services Designer
Add Operations
Create operations with appropriate HTTP verbs
CQRS Mapping
GET operations → Queries
POST/PUT/DELETE → Commands
Generate
Run the Software Factory to generate controllers and handlers
Installation
The module is automatically installed when you have both:
Intent.AspNetCore.Controllers
Intent.Application.MediatR
Dependencies
Intent.Application.MediatR (>= 4.3.0)
Intent.AspNetCore.Controllers (>= 7.1.0)
Intent.Modelers.Services.CQRS
Next Steps
MediatR Behaviors Add validation, logging, and other pipeline behaviors
CQRS Generate CQRS handlers automatically
FluentValidation Add request validation
Controllers Learn more about controller generation