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

1
private async Task<ActionResult> BlockContent<T>(PostData data) where T : BaseModel, IBlockableContent

and use it like you would any other generic method:

1
2
3
4
5
6
7
8
[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:

1
public sealed record Command<T>(long ObjectId, string Reason) : IRequest<ActionResult> where T : BaseModel, IBlockableContent;
1
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:

1
2
3
4
5
6
7
8
9
10
11
[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”