47

Please see the code below:

public class CreatePersonHandler
    : IRequestHandler<CreatePersonCommand,bool>
{
    public async Task<bool> Handle(CreatePersonCommand message, CancellationToken cancellationToken)
    {
        return true;
    }
}

It works as expected i.e. the hander is reached and returns true. How do I deal with the scenario where the handler returns nothing? I want to do this:

public async void Handle(CreatePersonCommand message, CancellationToken cancellationToken)
{
    //don't return anything
}

I have spent the last two hours Googling this. For example, I have looked here: Register a MediatR pipeline with void/Task response and here: https://github.com/jbogard/MediatR/issues/230.

Peter Bons
  • 26,826
  • 4
  • 50
  • 74
w0051977
  • 15,099
  • 32
  • 152
  • 329

4 Answers4

93

Generally speaking, if a Task based method does not return anything you can return a completed Task

    public Task Handle(CreatePersonCommand message, CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }

Now, in MediatR terms a value needs te be returned. In case of no value you can use Unit:

    public Task<Unit> Handle(CreatePersonCommand message, CancellationToken cancellationToken)
    {
        return Task.FromResult(Unit.Value);
    }

or, in case of some async code somewhere

    public async Task<Unit> Handle(CreatePersonCommand message, CancellationToken cancellationToken)
    {
        await Task.Delay(100);

        return Unit.Value;
    }

The class signature should then be:

public class CreatePersonHandler : IRequestHandler<CreatePersonCommand>

which is short for

public class CreatePersonHandler : IRequestHandler<CreatePersonCommand, Unit>
Peter Bons
  • 26,826
  • 4
  • 50
  • 74
  • Thanks. This class is inheriting from a base class, which looks like this: public class IdentifiedCommandHandler : IRequestHandler, R> where T : IRequest. Is there anything I can do here? i.e. I need to have a second generic parameter. – w0051977 Feb 14 '19 at 11:49
  • How can I test that the function completed successfully using: Unit.Value; ? – w0051977 Feb 14 '19 at 13:54
  • @w0051977 it has no use to test `Unit.Value` since it is the MediatR representation of a Task based void. If you look at the source code you'll see it has [a default value assigned](https://github.com/jbogard/MediatR/blob/master/src/MediatR/Unit.cs#L14). – Peter Bons Feb 14 '19 at 15:21
  • Thank you. Would you just not test this method? The method is contained in a class with no instance variables and it does not return anything. – w0051977 Feb 15 '19 at 07:07
  • 5
    2023 update: Starting with v12.x, `IRequest` no longer inherits from `IRequest`, meaning all methods with return type `Task` should be changed to just `Task` and `return Unit.Value` to just `return;` Reference: https://github.com/jbogard/MediatR/wiki/Migration-Guide-11.x-to-12.0#void-handlers-irequest-and-irequesthandler – Griffin Mar 07 '23 at 17:33
  • It should be noted here, that if you don't use async/await, you can return `Unit.Task`, which is non-allocating (because it caches one single completed task that contains `Unit.Value`) – Tseng Apr 24 '23 at 11:42
14

In CreatePersonCommand , IRequest shouldn't have any response type specified :

public record CreatePersonCommand : IRequest

And in PersonCommandHandler, IRequestHandler would be like this :

public class PersonCommandHandler: IRequestHandler<PersonCommandHandler>

And then in your handle method :

public async Task<Unit> Handle(CreatePersonCommand request, CancellationToken cancellationToken)
{
    // Some Code 

    return Unit.Value;
}
Kaveh Naseri
  • 1,102
  • 2
  • 15
  • 24
4

Workaround solution for anyone who doesn't want to use Unit for some reason. You can create class named as VoidResult or EmptyResult then use it as return for all requests that returns nothing.

public class CreatePersonHandler : IRequestHandler<CreatePersonCommand, VoidResult>
M.Erkan Çam
  • 173
  • 1
  • 7
2

There's another abstract class named AsyncRequestHandler that is a wrapper class for a handler that asynchronously handles a request and does not return a response.

public class CreatePersonHandler : AsyncRequestHandler<CreatePersonCommand>
{
    protected override Task Handle(CreatePersonCommand request, CancellationToken ct)
    {
        // don't return anything
    }
}
br3nt
  • 9,017
  • 3
  • 42
  • 63
Ali Soltani
  • 9,589
  • 5
  • 30
  • 55