Handlers and routes implementation

The cart service implements the handlers that reflect the different actions that occur on cart data in the domain part of our service. As we will see later in this chapter, the handlers are associated with a specific request and are executed by the IMediator interface, which is provided by the MediatR library. Also, in this case, these classes are located in the Cart.Domain project.

Let's start by taking a look at the implementation of the CreateCartHandler class:

//Handlers/Cart/CreateCartHandler.cs

using
System;
...

namespace Cart.Domain.Handlers.Cart
{
public class CreateCartHandler : IRequestHandler<CreateCartCommand, CartExtendedResponse>
{
private readonly ICatalogService _catalogService;
private readonly IMapper _mapper;
private readonly ICartRepository _repository;

public CreateCartHandler(ICartRepository repository, IMapper
mapper, ICatalogService catalogService)
{
_repository = repository;
_mapper = mapper;
_catalogService = catalogService;
}

public async Task<CartExtendedResponse> Handle
(CreateCartCommand command, CancellationToken
cancellationToken)
{
var entity = new CartSession
{
Items = command.ItemsIds.Select(x => new CartItem {
CartItemId = new Guid(x), Quantity = 1 }).ToList(),
User = new CartUser { Email = command.UserEmail },
ValidityDate = DateTimeOffset.Now.AddMonths(2),
Id = Guid.NewGuid().ToString()
};

var result = await _repository.AddOrUpdateAsync(entity);

var response = _mapper.Map<CartExtendedResponse>(result);

var tasks = response.Items
.Select(async x => await _catalogService
.EnrichCartItem(x, cancellationToken));

response.Items = await Task.WhenAll(tasks);

return response;
}
}
}

The preceding code is the definition of the CreateCartHandler class, which performs the creation cart process. The class uses the constructor injection technique to resolve the dependencies through the dependency injection engine of ASP.NET Core. Furthermore, the handler class depends on the IMapper and ICartRepository interfaces: the IMapper interface is used to map the CartSession instances with the CartExtendedResponse response class, while the ICartRepository interface is used to store the cart data on Redis through the use of the AddOrUpdateAsync method. 

The handler assigns a new Guid to the entity and it adds a ValidityDate of 2 months. Furthermore, it also assigns the new cart items list to the cart session by setting a default quantity of 1 for each item. In a similar manner, the GetCartHandler class implements the reading operations based on the Id of the cart:

using System.Threading;
...

namespace Cart.Domain.Handlers.Cart
{
public class GetCartHandler : IRequestHandler<GetCartCommand,
CartExtendedResponse>
{
private readonly ICatalogService _catalogService;
private readonly IMapper _mapper;
private readonly ICartRepository _repository;

public GetCartHandler(ICartRepository repository, IMapper
mapper, ICatalogService catalogService)
{
_repository = repository;
_mapper = mapper;
_catalogService = catalogService;
}

public async Task<CartExtendedResponse> Handle(GetCartCommand
command, CancellationToken cancellationToken)
{
var result = await _repository.GetAsync(command.Id);
var extendedResponse = _mapper.Map<CartExtendedResponse>
(result);

var tasks = extendedResponse.Items
.Select(async x => await _catalogService
.EnrichCartItem(x, cancellationToken));

extendedResponse.Items = await Task.WhenAll(tasks);
return extendedResponse;
}
}
}

In this case, the Handle method executes the GetAsync(Guid id) method that's provided by the underlying repository interface and it maps the response to the CartExtendedResponse type. The last handler that's implemented by the Cart.Domain project increases or decreases the quantity of an item in a specific cart:

using System.Linq;
...

namespace Cart.Domain.Handlers.Cart
{
public class UpdateCartItemQuantity : IRequestHandler
<UpdateCartItemQuantityCommand, CartExtendedResponse>
{
private readonly ICatalogService _catalogService;
private readonly IMapper _mapper;
private readonly ICartRepository _repository;

public UpdateCartItemQuantity(ICartRepository repository,
IMapper mapper, ICatalogService catalogService)
{
_repository = repository;
_mapper = mapper;
_catalogService = catalogService;
}

public async Task<CartExtendedResponse> Handle(UpdateCartItemQuantityCommand command, CancellationToken cancellationToken)
{
var cartDetail = await
_repository.GetAsync(command.CartId);

if (command.IsAddOperation)
cartDetail.Items.FirstOrDefault(x => x.CartItemId ==
command.CartItemId)?.IncreaseQuantity();
else
cartDetail.Items.FirstOrDefault(x => x.CartItemId ==
command.CartItemId)?.DecreaseQuantity();

var cartItemsList = cartDetail.Items.ToList();

cartItemsList.RemoveAll(x => x.Quantity <= 0);

cartDetail.Items = cartItemsList;

await _repository.AddOrUpdateAsync(cartDetail);

var response = _mapper.Map<CartExtendedResponse>
(cartDetail);
var tasks = response.Items
.Select(async x => await
_catalogService.EnrichCartItem(x, cancellationToken));

response.Items = await Task.WhenAll(tasks);

return response;
}
}
}

The handler accepts UpdateCartItemQuantityRequest, which defines the CartId, CartItemId, and a Boolean that denotes whether the request is to increase or decrease the quantity of the specified item.

The handler uses the same dependencies that the other handlers do and it performs some additional checks about the removal of the item if the amount is equal to zero. If the quantity associated with CartItemId reaches 0, then the item is removed from the cart session; otherwise, the quantity is updated and the cart proceeds by updating the Redis store and retrieving cartDetail.

Now that our handlers are in place, we will define the controller classes that will expose the HTTP routes for the web service.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.47.221