Generic MediatR Handlers
Odd as it might be, I couldn’t find much information about it myself, so I thought I’ll share my findings instead. Perhaps it’ll be of help to those seeking answers in the future.
Creating a generic controller? Nothing could be easier, simply create a method with a signature like
private async Task<ActionResult> BlockContent<T>(PostData data) where T : BaseModel, IBlockableContent
and use it like you would any other generic method:
[HttpPost("story")]
public async Task<ActionResult> BlockStory(PostData data) => await BlockContent<Story>(data);
[HttpPost("chapter")]
public async Task<ActionResult> BlockChapter(PostData data) => await BlockContent<Chapter>(data);
[HttpPost("blogpost")]
public async Task<ActionResult> BlockBlogpost(PostData data) => await BlockContent<Blogpost>(data);
But how about using it with MediatR and the CQRS pattern..?
As it turns out, it’s fairly simple as well:
public sealed record Command<T>(long ObjectId, string Reason) : IRequest<ActionResult> where T : BaseModel, IBlockableContent;
public async Task<ActionResult> Handle(Command<T> request, CancellationToken cancellationToken)
and… that’s it. The IDE will complain about the type parameter in Command<T> being
unused, but such is life, the IDE doesn’t know that we use it down the road, in the
Handle() method. It serves as a bit of a marker, more than a proper type parameter.
And using this generic command and handler? As simple as using the generic action, actually:
[HttpPost("story")]
public async Task<ActionResult> BlockStory(BlockContent.Command<Story> data)
=> await _mediator.Send(data);
[HttpPost("chapter")]
public async Task<ActionResult> BlockChapter(BlockContent.Command<Chapter> data)
=> await _mediator.Send(data);
[HttpPost("blogpost")]
public async Task<ActionResult> BlockBlogpost(BlockContent.Command<Blogpost> data)
=> await _mediator.Send(data);
Just send the appropriate generic command, and voila!
This post might come off as a bit unnecessary, seeing how short and to the point it is, but I assure you, you will find no better explanation elsewhere. Everything I managed to find, at least, was either waaaay overcomplicated, or boiled down to “no can do”