Command Handlers return values in CQRS
I have recently come across this very interesting blog post by Jimmy Bogard ( the guy behind Mediatr, just FYI). He’s talking about CQRS, and makes a good point about how the user should be informed of the result of a Command execution.
Should the Command Handler return a value?
Should the Command Handler throw an exception?
These are just some of the strategies we may take. Another option could be to just log the operation and forget that anything happened. Whatever.
A while ago I blogged about how to validate the Commands and ensure the data passed to the Command Handler is valid. This is the strategy I’ve been adopting in my projects lately. Why? Well, several reasons: first of all I want to keep Command execution separated from the validation.
Moreover, Commands should be some sort of “fire and forget” operations. Let me clarify this a little bit.
In my opinion Command execution should be a boolean operation: the system can either execute it or not. Stop. I should be able to know ahead if a Command can be executed and that’s the validation phase. If I finally manage to get to the Handler, I know that the data I have is valid and I can run Command. No need to return a “true”.
So what should I do to make all the pieces fit?
- Use a strategy to ensure each Command is validated before execution. For example:
- Decorator pattern
- External validation class injected into the Command Handler
- The Validator should analyze the Command and check its validity against business rules or anything else you want
- the Validator gives back a Validation result containing a (hopefully empty) list of errors
- in case something went wrong, throw a specialized Exception, for example, something like this.
Since most of the projects I am working on lately is composed of some sort of Web API based on .NET Core, I also decided to create an Exception Filter. It will eventually return to the user a JSON object with the details of the validation:
public class ExceptionFilter : IExceptionFilter { public void OnException(ExceptionContext context) { int status = ExtractHttpStatus(context); var errorInfo = _apiErrorFactory.Create((dynamic)context.Exception); context.Result = new ObjectResult(errorInfo) { StatusCode = status, DeclaredType = errorInfo.GetType() }; } }
**Bonus
** You may have noticed that some of the links in this post point to this Github repository, LibCore. It’s a small set of utilities I am writing, maintaining and using in my projects. I thought it would be useful to share the sources, maybe just to hear comments from the community. Food for thought.