C
C#4w ago
Cali_West

✅ How much validation should be performed against the CQRS command itself vs in the handler?

For example, let's say I have a database with this schema:
Persons Cities
-------- ---------
Id CHAR(36) Id CHAR(36)
Residence CHAR(36) FK->Cities.Id Name TEXT
Name TEXT Country TEXT
Age INT
Birthday DATE
Persons Cities
-------- ---------
Id CHAR(36) Id CHAR(36)
Residence CHAR(36) FK->Cities.Id Name TEXT
Name TEXT Country TEXT
Age INT
Birthday DATE
and the command is to invite a bunch of people to their birthday party, but only people who live in the same city are allowed to come, and the invitation must be sent at some point in the 30 days prior to the party date, and the party date has to be within +-7 days of their actual birthday:
public class SendBirthdayInvitationCommand : IRequest
{
public Guid Host { get; set; }
public DateTime PartyDate { get; set; }
public IEnumerable<Guid> Guests { get; set; }
}
public class SendBirthdayInvitationCommand : IRequest
{
public Guid Host { get; set; }
public DateTime PartyDate { get; set; }
public IEnumerable<Guid> Guests { get; set; }
}
So, as far as validation of the command itself goes, I see two options: 1) Validate that the Host and all the Guests are not equal to Guid.Empty, and that the PartyDate is some time in the next 30 days. And that's as far as I could really go without a DbContext. Then in the handler, I would actually do the rest of the validation. 2) Inject a DbContext into the command validator and then I'd be able to validate everything before it even reaches the handler, and then the job of the handler would be reduced to just the act of actually sending out the invitations (however that happens). Which is generally considered to be the better pattern? I have a feeling that #1 is the better pattern, for two reasons. One is that doing all that validation outside the handler feels like "hiding" it. And two is that doing all that validation outside the handler would take the query that the handler is going to have to send and effectively turn it into work that's already been done, and therefore just making the handler re-send the same query that the validator has already sent. But I just thought I'd get a second opinion.
8 Replies
Pobiega
Pobiega4w ago
Generally, commands only do basic input validation. This should be quick and cheap, so stuff like "hey this is empty, we need a non-empty string" or "that number is too big/small". for stuff like "this value already exists in the database"; thats something the handler takes care of
Mayor McCheese
Imho number 1 is more nuanced, you're validating that you can try to process the command. When you say as far as you can go, you might be robbing what should be in the handler. But you may even have a model that gets validated and converted to a command and then handled.
Cali_West
Cali_WestOP4w ago
okay so it does sound like #2 is going way too far
Mayor McCheese
Async validators tend to be problematic imho
Cali_West
Cali_WestOP4w ago
okay. Thank you! I really just needed a second opinion on it. I think that answers my question. How do I remove this post?
Mayor McCheese
Don't
Cali_West
Cali_WestOP4w ago
oh okay
Mayor McCheese
There's is a close command /close
Want results from more Discord servers?
Add your server