Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
April 25, 2023 09:25 pm GMT

Easiest way to build the fastest REST API in C and .NET 7 using CQRS

Sometime ago I stumbled upon this amazing library built by amazing people: https://fast-endpoints.com

It was also featured on this platform https://dev.to/djnitehawk/building-rest-apis-in-net-6-the-easy-way-3h0d (written by the author).

I gave it a go and I was impressed how easy and fast it was to set it all up. Since I'm not a big fan of REPR pattern almost all my projects are using CQRS pattern with a help of MediatR ](https://github.com/jbogard/MediatR) I immediately started going over something similar that Fast Endpoints offer which is a command bus.

I immediately started to put the project together with certain goals:

  1. Keep everything in command/query handlers
  2. Keep API as thin as possible
  3. Execute handlers within Azure Functions (keeping them thin as well)
  4. Make handlers easily unit testable

I put all this up on Github FastArchitecture

The API endpoint ended up being a single line:

public class GetOrdersEndpoint : ApiEndpoint<GetOrders.Query, GetOrders.Response>{    public override void Configure()    {        Get("orders/list");        AllowAnonymous();        ResponseCache(60);    }    public override async Task HandleAsync(GetOrders.Query request, CancellationToken ct)        => await SendAsync(await request.ExecuteAsync(ct));}

The Query handler in a self contained class that contains:

  • Query definition (the input)
  • Query response (the output)
  • Handler (stuff that happens within execution)
public static class GetOrders{    public sealed class Query : IQuery<IHandlerResponse<Response>>    {    }    public sealed class Response    {        public IReadOnlyCollection<OrderListModel> Orders { get; private set; }        public Response(IReadOnlyCollection<Domain.Order> orders)        {            Orders = orders.Select(OrderListModel.Create).ToList();        }    }    public sealed class Handler : QueryHandler<Query, Response>    {        public Handler(IHandlerContext context) : base(context)        {        }        public override async Task<IHandlerResponse<Response>> ExecuteAsync(Query query, CancellationToken ct)        {            var orders = await DbContext                .Orders                .ToListAsync(ct);            return Success(new Response(orders));        }    }}

Here is an example of Command handler with built-in Fluent Validation and fire and forget style:

public static class ConfirmAllOrders{    public sealed class Command : ICommand    {        public string Name { get; set; } = "";    }    public sealed class MyValidator : Validator<Command>    {        public MyValidator()        {            RuleFor(x => x.Name)                .MinimumLength(5)                .WithMessage("Order name is too short!");        }    }    public sealed class Handler : Abstractions.CommandHandler<Command>    {        public Handler(IHandlerContext context) : base(context)        {        }        public override async Task<IHandlerResponse> ExecuteAsync(Command command, CancellationToken ct)        {            var orders = await DbContext                   .Orders                   .ToListAsync(ct);            orders.ForEach(x => x.SetConfrimed());            await DbContext.SaveChangesAsync(ct);            return Success();        }    }}

Handlers allow 3 possible responses:

  1. Response without content:
return Success()
  1. Response with some content:
return Success(responseObj)
  1. An error*:
return Error("I felt a great disturbance in the Force, as if millions of voices suddenly cried out in terror and were suddenly silenced. I fear something terrible has happened.")

*soon to be implemented

Here is an example of running it from ** Azure Functions**:

public class ConfirmAllOrdersFunction : FunctionBase<ConfirmAllOrdersFunction>{    public ConfirmAllOrdersFunction(ILogger logger) : base(logger)    {    }    [Function(nameof(ConfirmAllOrdersFunction))]    public async Task Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req)    {        var command = new ConfirmAllOrders.Command();        await ExecuteAsync<ConfirmAllOrders.Command>(command, req.FunctionContext);    }}

Interested?
Checkout the complete source code on Github FastArchitecture


Original Link: https://dev.to/kedzior_io/easiest-way-to-build-the-fastest-rest-api-in-c-and-net-7-using-cqrs-2bk8

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To