Мне нравится возвращать события из моих команд.Команда сообщает вашему приложению, чего хочет от него клиент.Ответ - то, что он фактически сделал.
Кстати, говорят, что обработчики команд должны возвращать что угодно.Это действительно верно только в полностью асинхронной среде, где команда не будет выполнена до тех пор, пока не будет принят ответ клиенту.В этом случае вы вернете Task<Unit>
и опубликуете эти события.Клиент получит их через какой-то другой канал, например концентратор SignalR, когда они будут подняты.В любом случае, события - это лучший способ рассказать клиенту, что происходит в вашем приложении.
Начните с определения интерфейса для ваших событий
public interface IEvent
{
}
Затем создайте события для каждого извещи, которые могут произойти в команде.Вы можете включить в них информацию, если хотите что-то сделать с этой информацией, или просто оставить их пустыми, если сам класс достаточен.
public class CourseNotFoundEvent : IEvent
{
}
public class CourseDeletedEvent : IEvent
{
}
Теперь ваша команда вернет интерфейс событий.
public class DeleteCourseCommand : IRequest<IEvent>
{
}
Ваш обработчик будет выглядеть примерно так:
public class DeleteCourseCommandHandler : IRequestHandler<DeleteCourseCommand, IEvent>
{
private readonly UniversityDbContext _context;
public DeleteCourseCommandHandler(UniversityDbContext context)
{
_context = context;
}
public async Task<IEvent> Handle(DeleteCourseCommand request, CancellationToken cancellationToken)
{
var course = await _context.Courses.FirstOrDefaultAsync(c => c.Id == request.Id, cancellationToken);
if (course is null)
return new CourseNotFoundEvent();
_context.Courses.Remove(course);
var saveResult = await _context.SaveChangesAsync(cancellationToken);
if (saveResult <= 0)
{
throw new DeleteFailureException(nameof(course), request.Id, "Database save was not successful.");
}
return new CourseDeletedEvent();
}
}
Наконец, вы можете использовать сопоставление с шаблоном в своем веб-API для выполнения действий на основе возвращаемого события.
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(int id)
{
var @event = await Mediator.Send(new DeleteCourseCommand {Id = id});
if(@event is CourseNotFoundEvent)
return NotFound();
return NoContent();
}