WebApi + ClientApp, GraphQL, Reflection

This commit is contained in:
Boris Milašinović
2026-05-06 20:55:05 +02:00
parent 8f7c704a90
commit 4fb3de19f6
196 changed files with 10395 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
using AutoMapper;
using Events.WebAPI.Contract.DTOs;
using Events.WebAPI.Handlers.EF.CommandHandlers.Generic;
using Events.WebAPI.Handlers.EF.Data.Postgres;
using Events.WebAPI.Handlers.EF.Models;
using Microsoft.Extensions.Logging;
namespace Events.WebAPI.Handlers.EF.CommandHandlers;
public class EventsCommandsHandler : GenericCommandHandler<Event, EventDTO, int>
{
public EventsCommandsHandler(EventsContext ctx, ILogger<EventsCommandsHandler> logger, IMapper mapper)
: base(ctx, logger, mapper)
{
}
}

View File

@@ -0,0 +1,56 @@
using MobilityOne.Common.Commands;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Events.WebAPI.Contract.Command;
using Events.WebAPI.Contract.DTOs;
using AutoMapper;
namespace Events.WebAPI.Handlers.EF.CommandHandlers.Generic;
public class GenericCommandHandler<TDal, TDto, TPK> : IRequestHandler<AddCommand<TDto, TPK>, TPK>,
IRequestHandler<UpdateCommand<TDto>>,
IRequestHandler<DeleteCommand<TDto, TPK>>
where TDal: class, IHasIdAsPK<TPK>
where TDto: IHasIdAsPK<TPK>
where TPK : IEquatable<TPK>
{
protected DbContext Ctx { get; }
protected ILogger Logger { get; }
protected IMapper Mapper { get; }
protected GenericCommandHandler(DbContext ctx, ILogger logger, IMapper mapper)
{
Ctx = ctx;
Logger = logger;
Mapper = mapper;
}
public virtual async Task<TPK> Handle(AddCommand<TDto, TPK> request, CancellationToken cancellationToken)
{
var entity = Mapper.Map<TDto, TDal>(request.Dto);
Ctx.Add(entity);
await Ctx.SaveChangesAsync(cancellationToken);
return entity.Id;
}
public virtual async Task Handle(UpdateCommand<TDto> request, CancellationToken cancellationToken)
{
var entity = await Ctx.Set<TDal>().FindAsync(request.Dto.Id);
if (entity != null)
{
Mapper.Map(request.Dto, entity);
await Ctx.SaveChangesAsync(cancellationToken);
}
else
{
Logger.LogError($"UpdateCommand<{typeof(TDto).Name}> : Invalid id #{request.Dto.Id}");
throw new ArgumentException($"Invalid id: {request.Dto.Id}");
}
}
public virtual async Task Handle(DeleteCommand<TDto, TPK> request, CancellationToken cancellationToken)
{
await Ctx.Set<TDal>().Where(d => d.Id.Equals(request.Id)).ExecuteDeleteAsync(cancellationToken);
}
}

View File

@@ -0,0 +1,16 @@
using AutoMapper;
using Events.WebAPI.Contract.DTOs;
using Events.WebAPI.Handlers.EF.CommandHandlers.Generic;
using Events.WebAPI.Handlers.EF.Data.Postgres;
using Events.WebAPI.Handlers.EF.Models;
using Microsoft.Extensions.Logging;
namespace Events.WebAPI.Handlers.EF.CommandHandlers;
public class PeopleCommandsHandler : GenericCommandHandler<Person, PersonDTO, int>
{
public PeopleCommandsHandler(EventsContext ctx, ILogger<PeopleCommandsHandler> logger, IMapper mapper)
: base(ctx, logger, mapper)
{
}
}

View File

@@ -0,0 +1,93 @@
using AutoMapper;
using Events.WebAPI.Contract.Command;
using Events.WebAPI.Contract.DTOs;
using Events.WebAPI.Contract.Messages;
using Events.WebAPI.Handlers.EF.CommandHandlers.Generic;
using Events.WebAPI.Handlers.EF.Data.Postgres;
using Events.WebAPI.Handlers.EF.Models;
using MassTransit;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using MobilityOne.Common.Commands;
namespace Events.WebAPI.Handlers.EF.CommandHandlers;
public class RegistrationsCommandsHandler : GenericCommandHandler<Registration, RegistrationDTO, int>
{
private readonly IPublishEndpoint publishEndpoint;
public RegistrationsCommandsHandler(
EventsContext ctx,
ILogger<RegistrationsCommandsHandler> logger,
IMapper mapper,
IPublishEndpoint publishEndpoint)
: base(ctx, logger, mapper)
{
this.publishEndpoint = publishEndpoint;
}
public override async Task<int> Handle(AddCommand<RegistrationDTO, int> request, CancellationToken cancellationToken)
{
int id = await base.Handle(request, cancellationToken);
await publishEndpoint.Publish(new RegistrationCreated
{
RegistrationId = id,
PersonId = request.Dto.PersonId,
EventId = request.Dto.EventId,
SportId = request.Dto.SportId
}, cancellationToken);
return id;
}
public override async Task Handle(UpdateCommand<RegistrationDTO> request, CancellationToken cancellationToken)
{
var entity = await Ctx.Set<Registration>().SingleOrDefaultAsync(r => r.Id == request.Dto.Id, cancellationToken);
if (entity == null)
{
Logger.LogError("UpdateCommand<{DtoName}> : Invalid id #{Id}", typeof(RegistrationDTO).Name, request.Dto.Id);
throw new ArgumentException($"Invalid id: {request.Dto.Id}");
}
int previousPersonId = entity.PersonId;
int previousEventId = entity.EventId;
int previousSportId = entity.SportId;
await base.Handle(request, cancellationToken);
await publishEndpoint.Publish(new RegistrationUpdated
{
RegistrationId = request.Dto.Id,
PersonId = request.Dto.PersonId,
EventId = request.Dto.EventId,
SportId = request.Dto.SportId,
PreviousPersonId = previousPersonId,
PreviousEventId = previousEventId,
PreviousSportId = previousSportId
}, cancellationToken);
}
public override async Task Handle(DeleteCommand<RegistrationDTO, int> request, CancellationToken cancellationToken)
{
var entity = await Ctx.Set<Registration>()
.AsNoTracking()
.SingleOrDefaultAsync(r => r.Id == request.Id, cancellationToken);
if (entity == null)
{
Logger.LogError("DeleteCommand<{DtoName}> : Invalid id #{Id}", typeof(RegistrationDTO).Name, request.Id);
throw new ArgumentException($"Invalid id: {request.Id}");
}
await base.Handle(request, cancellationToken);
await publishEndpoint.Publish(new RegistrationDeleted
{
RegistrationId = entity.Id,
PersonId = entity.PersonId,
EventId = entity.EventId,
SportId = entity.SportId
}, cancellationToken);
}
}

View File

@@ -0,0 +1,17 @@
using AutoMapper;
using Events.WebAPI.Contract.DTOs;
using Events.WebAPI.Handlers.EF.CommandHandlers.Generic;
using Events.WebAPI.Handlers.EF.Data.Postgres;
using Events.WebAPI.Handlers.EF.Models;
using Microsoft.Extensions.Logging;
namespace Events.WebAPI.Handlers.EF.CommandHandlers
{
public class SportsCommandsHandler : GenericCommandHandler<Sport, SportDTO, int>
{
public SportsCommandsHandler(EventsContext ctx, ILogger<SportsCommandsHandler> logger, IMapper mapper)
: base(ctx, logger, mapper)
{
}
}
}