Any of these sound familiar?
Rubbish in rubbish out.
Never trust user input.
If you’ve ever built any sort of professional application you will have had to validate user input. Whether it is to ensure a valid email address or something more complicated. There are tried and tested ‘rules’ for doing this safely while being nice the user.
- Validate on the client side – makes for a better user experience
- And validated on the server – never trust user input
But here’s a question..
If you issue commands rather than send in models, where should the validation occur?
The most obvious answer is in the domain model.
But this poses a problem…
Commands are handled by methods with no return type. Just take a look at the Aggregate Root for an example. Not only that, they are not necessarily processed right away. Before I dive into how to validate your commands, let’s just cover how normal validation works. Just to be clear, a CQRS command is not the same as the Command pattern made popular by the GoF. If you are unsure of the difference, take a look at this post here.
How Validation is Normally Done
Given client side validation cannot be trusted, most developers start validation by ensuring the server side is bullet proof. The user fills in a form and submits a model to the server. The server would then apply a set of logic to determine if the model is valid. The code for this is normally centralised. I.e. all the validation logic is kept together. Importantly all validation is treated as one. There is no separation between superficial type validations like, email or domain concepts like ‘package too heavy for transporter’.
Once the server validation is working it is then applied to the client side for a better user experience.
How Do You Validate Commands?
As I hinted above, the trick is to differentiate between superficial validation and domain validation. In short, there are 2 types of validation and they belong in different places.
What is Superficial Validation?
Required fields, email formatting, valid dates are all examples of superficial validation. The key here is to think, what is true regardless of the state of the domain. If a field is required, it is required whether or not the domain model will accept the command or not.
These kind of validations should be done before the command is issued. At least on submission of the form but ideally on the client as well.
FluentValidation Is A Good For Superficial Validation
I’ve found FluentValidation to be a convenient package for validating commands. And with a bit of convention over configuration, you can save yourself a fair bit of typing.
What is the convention?
Just post fix the name of the class with the validation rules with the name of the class being validated. Simples. Here is how it might look:
public class ImportStressTest : Command { public readonly Guid AggregateId; public readonly int Version; public readonly Guid UserId; public readonly Guid ReportId; public readonly string Data; public ImportStressTest(Guid aggregateId, int version, Guid userId, Guid reportId, string data) { AggregateId = aggregateId; Version = version; UserId = userId; ReportId = reportId; Data = data; } } public class ImportStressTestValidator : AbstractValidator<ImportStressTest> { public ImportStressTestValidator() { RuleFor(message => message.AggregateId).NotEmpty(); RuleFor(message => message.Version).GreaterThanOrEqualTo(0); RuleFor(message => message.UserId).NotEmpty(); RuleFor(message => message.ReportId).NotEmpty(); RuleFor(message => message.Data).NotEmpty(); } }
Having established the convention you will want to take advantage of this in your internal message bus. Add logic to the message bus which checks for the existence of a validator for any given command. It can then run the validator before issuing the command.
What is Domain Based Command Validation?
This is where the validity of a command is dependant on the state of the model. For example it may be valid to transport package that weighs a ton in one vehicle but not in another. The reason for the difference is found within the domain logic.
It can get a bit confusing here when you have what looks like superficial validation but is actually domain based. For example a field which is required in certain circumstances. E.g. a workflow may require a note of explanation if withdrawing some live data but not if withdrawing draft data. The rule of thumb is – if it needs domain state then it lives in the domain.
As always there are exceptions. Sometimes your validation logic will need data from the wider system to work. This means it’s not superficial validation but it also doesn’t need the domain model. This kind of validation usually sits with an application service. It is typically run before the command reaches the domain.
How do you return the validation errors?
This is a common problem. A key facet of using commands is not having a return type. That is a command, is ultimately handled by a method with a void return type. This leaves us with only 1 option, throw an exception.
Not entirely true, and here’s why…
Working from the domain out to the client, here are 4 ways you could do validation in a CQRS application. The right way for your application maybe 1 of the four or more likely a combination.
Domain Side
- 1) Throw an exception in the domain.
- 2) Publish an event detailing validation problems
Server Side:
- 3) Throw an HTTP error code
- 4) And/Or use a ‘Common Result Object’.
1. Throwing an Exception in the Domain
Throwing a domain side validation exception assumes your commands are handled within the normal flow of the application rather than being queued for later actioning. It doesn’t have to be synchronous but it is much simpler. The problem here is that unwinding the stack to throw an exception can be costly on server performance. You should therefore reserve this approach for truly exceptional cases or low traffic systems.
Here is a simplistic example I stole from my article about how to build aggregate roots.
public void BookHoliday(BookHoliday command) { // Ensure the invariants would not be broken by the command var totalDaysRequested = (command.EndDate - command.StartDate).TotalDays; var combinedTotal = totalDaysRequested + _totalDaysTaken; if (combinedTotal > totalAllocated) throw new NotEnoughHolidaysRemainingException(); // 2nd Phase - Create and commit the event ApplyChange(new HolidayBooked(command.AggregateId, command.Version, command.UserId, command.StartDate, command.EndDate)); }
2. Publishing an Event Describing the Problem
Publishing an event is rather more interesting. I helped a subscriber of this blog with a problem around how to handle invalid commands. In his case users had to ‘clock-in’ to a location then ‘log work’ done. The problem was the client devices were frequently offline. It was also possible for users to forget to clock-in or out or even log work to the wrong location. Because of the offline issue, commands had to be accepted even when they appeared to be invalid.
The solution was for the domain to raise an event when it detected an issue. The application could then raise a flag for the admins who could call the operator and clarify what was supposed to have been logged.
3. Throwing an HTTP Error Code
You can use HTTP error codes on the server side. Usually a 400 bad request is ideal for validation problems.
But there is another way…
4. Simplify Your Life with the Common Result Object
I first saw something similar when working with the ServiceStack framework. The framework allowed you to add a ResponseStatus to any return object. It had a common shape and would be a good place to add validation failures. Rob Conery went a step further by suggesting returning a CommonResult from every server request.
But commands are handled by void methods – how do you return a common result?
Just because the methods on your domain object are void, does not mean your HTTP endpoints need to also be void (or 200 ok). By creating a convention that every endpoint which handles commands or queries must return a CommonResult object, you can greatly simplify a whole host of operations including validation.
The CommonResult object would typically look like this:
public interface ICommonResult
{
dynamic Data { get; }
int TotalResults { get; }
string FlashMessage { get; }
bool Success { get; }
}
This common result object should not contain exception details or stack traces. This is to ensure you do not leak potentially sensitive data.
Hold on – returning data from a command! Isn’t that breaking the basic approach to CQRS?
Think about it…
The domain model still returns void or throws an exception when a command is executed. The distinction here is we can check the superficial validity before the command is ever executed. Just to be clear, the http endpoint returns the CommonResult object when a command is issued. The domain model doesn’t – it’s still void. So you can handle superficial validation errors and domain validation errors/exceptions.
Summary
There are 4 places validation takes place in CQRS system.
- Client side
- Server side
- Application service
- Domain Objects
The first two are for Superficial Validations such as required fields etc. The application service is the right place for superficial validations which requires lookup information. Finally, any validation which requires domain logic sits in the domain. Validation failures in the domain do not necessarily need to throw exceptions, events can also be raised for more advanced scenarios.
If you have found this article helpful, please share with your social networks.
Excellent post – thanks.
One other way to do validation (which is more applicable to IoT or automated systems maybe) is to have any commands that fail on the server side passed into a “poisoned messages” storage which in turn can be queried by a “how did my command get on” query.
The logic behind this method is partly that even if a command fails we want to record that it was issued and there may be a “try again” process we can invoke (depending on the command – some can, others not)
Would this scenario not be covered by the “raise an event” option which would need to contain a reference to the failed command in order to be useful anyway?
That could also work. I think Merrions point is that he is explicitly recording a failed or poisoned command.
Can I ask why you opted for a dynamic data type over a using a generic ICommonResult ?
Hey Daniel, great article! I could not see the CQRS and DDD very well, but after reading this article I think the Application Service can be used in the Command too. Before I thought the command could not use the Application Service, and only the Read could use. Am I right about that?
“As always there are exceptions. Sometimes your validation logic will need data from the wider system to work. This means it’s not superficial validation but it also doesn’t need the domain model. This kind of validation usually sits with an application service. It is typically run before the command reaches the domain.”
I want to create a aggregate A (it is related to other aggregate B & C, inshort A is the connection b/w B & C) but only if the it doesn’t exist (I don’t want to create duplicate connection for B & C (i.e A) ).
Where should I put the logic for this?
In Command Handler?
Should I use Read Models/ Queries for this ?
Right now I am doing something like this in command handler only ->
AggregateB b = GetById(bAggregateId); //create aggregate by replaying event on aggregate
AggregateC c = GetById(cAggregateId); /create aggregate by replaying event on aggregate
if(b exists && c exists)
{
AReadModel aReadModel= query.GetAReadModelBy_B&C(bAggregateId,cAggregateId)
if(aReadModel not exists)
{
// Create New A AggregateA
}
}
Can you please give some advice on this ?
Is this correct way?
It would be very helpful
A design feature of an aggregate is that it does not have dependencies. The fact that A and B need to know stuff about each other would be suggestive of a design smell. I would suggest you look at the aggregate design. Maybe they should all be one aggregate?
Alternatively, let’s assume this connection is valid. After all, I don’t know your system. It would probably make sense to have data in the read model which you can check before issuing the command. You may need to handle the possibility of the read model being out of date when the check occurs. If this is a big issue (it very rarely is), you can create a compensating event(s) to fix.
Apologies for the delayed reply.
Obviously I don’t know your specific domain or the specific problem you are facing so my answer is more generic. Typically when I see this ‘aggregate connects to this aggregate’ it’s a strong indication there is a design flaw in the aggregates. The word aggregate implies that it is a combination of classes accessed via a single api. It should be self-contained and referenced by ID. In other words, it shouldn’t need to check something else is created before it can be created.
Look to see if your aggregate boundaries are right first.
Thank you very much for sharing the informative post. I like it very much. I have a question, If I execute a command asynchronously (from bus), then what is the meaning of returning ICommonResult? In that case, what we will do should we raise event and we will notify the client through web socket/signalR?
– If the client is not alive/online then how we should manage that validation result?
Thanks in advance.
[…] can see an example of this approach in Daniel Whittaker’s blogwhere he discusses using command execution objects to test them. Moreover, in this example you can […]
[…] Whittaker advocates returning a “common result” object from a command handler containing this […]