/MediatR.AspNet

Easy implement CQRS with MediatR in ASP.Net Core

Primary LanguageC#MIT LicenseMIT

https://www.nuget.org/packages/MediatR.AspNet/ GitHub issues GitHub license

MediatR.AspNet

CQRS support for MediatR in ASP.Net.

Made as .Net 6.0 library.

-> Changelog

Features

  • interface IQuery<T>
  • interface ICommand<T>
  • custom Exceptions:
    • ExistsException
    • DeletedNotAllowedException
    • NotFoundException
    • OperationNotAllowedException
    • UpdateNotAllowedException
    • NotAuthorizedException
  • custom Exception Middleware
  • possibility to create custom exceptions

Usage

Configuration

  1. Add Nuget package from here.
  2. In Program.cs of your project:
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));
builder.Services.AddApplicationExceptions();

app.UseApplicationExceptions();

You can see Demo Project here

Example usage

Example for GetById endpoint:

  1. Create model:
public class Product {
    public int Id { get; set; }
    public string Name { get; set; }
}
  1. Create model Dto:
public class ProductDto {
    public int Id { get; set; }
    public string Name { get; set; }
}
  1. Create GetByIdQuery:
public class GetProductByIdQuery : IQuery<ProductDto> {
    public int Id { get; set; }
}
  1. Create GetByIdQueryHandler:
public class GetProductByIdQueryHandler: IRequestHandler<GetProductByIdQuery, ProductDto> {
        
    private readonly ProductContext _context;
        
    public GetProductByIdQueryHandler(ProductContext context) {
        _context = context;
    }
        
    public Task<ProductDto> Handle(GetProductByIdQuery request, CancellationToken cancellationToken) {
        var productEntity = await _context.Products
            .Where(a => a.ProductId == request.id);
        if (productEntity == null) {
            throw new NotFoundException(typeof(Product), request.Id.ToString());
        }

        return Task.FromResult(productEntity.toDto());
    }
}
  1. Usage in controller:
[ApiController]
[Route("[controller]")]
public class ProductsController : ControllerBase {
        
    private readonly IMediator _mediator;

    public ProductsController(IMediator mediator) {
        _mediator = mediator;
    }
        
    [HttpGet("{id}")]
    public async Task<ProductDto> GetById([FromRoute]int id) {
        var query = new GetProductByIdQuery {
            Id = id
        };
        return await _mediator.Send(query);
    }
}

Creating custom exception

Custom exception must inherit from the class BaseApplicationException:

public class MyCustomException : BaseApplicationException {
    public MyCustomException() : base("I'm a teapot", StatusCodes.Status418ImATeapot, "I'm a custom teapot") { }
}

The constructor require code, status and message.

Development

We are happy to accept suggestions for further development. Please feel free to add Issues :)

Authors

License

This project is licensed under the MIT License - see the LICENSE file for details.