I have an ASP.NET MVC application, that uses a query service to get data and a command service to send commands. My question is about the command part.

If a request comes in, the command service uses a command dispatcher that will route the command to its designated command handler. This command handler validates the comand first and if everything is acceptable, it executes the command.

Concrete example: the AddCommentToArticleCommandHandler receives an AddCommentToArticleCommand, which has an ArticleId, CommentText and EmailAddress.

First; validation has to occur, like: - check if article exists - check if article is not closed - check if comment text is filled in and between 20 and 500 characters - check if email address is filled in and has a valid format.

I'm wondering where to put this validation?

1/ in the command handler itself. But then, it cannot be reused in other command handlers.

2/ in the domain entity. But as a domain entity doesn't know about repositories or services, it cannot do the needed validation (cannot check whether an article exists). But on the other hand, if the entity doesn't contain logic, than it becomes a simple data container, which is not following DDD principles.

3/ the command handler uses validators, so that validation can be reused in other command handlers.

4/ Other mechanisms?

I'm looking for the chain of responsibilities for this particular example and what objects (entities, repositories, ...) play a role in it.

Do you have ideas on how you would implement this, starting from the command handler up to the repositories?


2 Answers 2


I think you need to separate two types of validation in this case; domain validation and application validation.

Application validation is what you have when you verify that the command property 'text' is between 20 and 200 characters; so you validate this with the GUI and with a view-model-validator that also executes at the server after a POST. The same goes for e-mail (btw, I hope you realize that an e-mail such as `32.d+"Hello World .42"@mindomän.local" is a valid according to the RFC).

Then you have another validation; check that article exists - you have to ask yourself the question why the article should not exist if there is indeed a command sent from the GUI that is about attaching a comment to it. Was your GUI eventually consistent and you have an aggregate root, the article, that can be physically deleted from the data store? In that case you just move the command to the error queue because the command handler fails to load the aggregate root.

In the above case, you would have infrastructure that handles poison messages - they would for example retry the message 1-5 times and then move it to a poision queue where you could manually inspect the collection of messages and re-dispatch those relevant. It's a good thing to monitor.

So now we've discussed:

  • Application validation

    • With javascript in the GUI
    • With MVC-validation at the web server
  • Missing aggregate root + poison queues

What about commands that are out of sync with the domain? Perhaps you have a rule in your domain logic saying that after 5 comments to an article, only comments below 400 characters are allowed, but one guy was too late with the 5th comment and got to be the 6th - GUI didn't catch it because it was not consistent with the domain at the point of him sending his command - in this case you have a 'validation failure' as a part of your domain logic and you would return the corresponding failure event.

The event could be in the form of a message onto a message broker or your custom dispatcher. The web server, if the application is monolithic, could synchronously listen for both a success event and the failure event mentioned and display the appropriate view/partial.

Often you have custom event that means failure for many types of commands, and it is this event that you subscribe to from the web server's perspective.

In the system that we are working on, we're doing request-response with commands/events over a MassTransit+RabbitMQ message bus+broker and we have an event in this particular domain (modelling a workflow in part) that is named InvalidStateTransitionError. Most commands that try to move along an edge in the state graph may cause this event to happen. In our case, we're modelling the GUI after an eventually consistent paradigm, and so we send the user to a 'command accepted' page and thereafter let the web server's views update passively through event subscriptions. It should be mentioned that we are also doing event-sourcing in the aggregate roots (and will be doing for sagas as well).

So you see, a lot of the validation you are talking about are actually application-type validations, not actual domain logic. There's no problem in having a simple domain model if your domain is simple but you are doing DDD. As you continue modelling your domain, however, you'll discover that the domain might not be as simple as it first turned out. In many cases the aggregate root/entity might just accept a method invocation caused by a command and change some of its state without even performing any validation - especially if you trust your commands like you'd do if you validate them in the web server that you control.

I can recommand watching the two presentations on DDD from Norwegian Developer Conference 2011 and also Greg's presentation at Öredev 2010.

Cheers, Henke

  • Thanks! One thing about validation: at the moment, this validation is triggered by the UI (by issuing a Validate(command) request to the service), which uses the Validate() of the Comment entity itself. Then, if the command is valid, the client issues an Execute command, which will again execute the Validate() to be sure, and if valid the actual command is executed. So the main validation is done by the Comment entity, because in every context the validation will be the same (email always has to be valid, comment text not too long, etc.) Is this a good approach?
    – L-Four
    Sep 23, 2011 at 12:48
  • The validation that you seem to be describing doesn't seem to me to warrant modelling it with a 2-phase validation protocol - sure, validate the method invocation's parameters on the entity like you'd test in a unit test, but besides this; the application layer/GUI could easily validate the rules that you are describing without sending commands to the domain. Imo. Unless the client is malicious the command should then work. If the client is malicious then the command fails and your read model never gets a corresponding event and you can inspect the problematic command in error queue.
    – Henrik
    Sep 23, 2011 at 16:05
  • In the UI (ASP.NET MVC) I'm using validation attributes to do all validation. So if this validation succeeds, I do not have to validate again on the domain then, but just execute the command?
    – L-Four
    Sep 23, 2011 at 22:14
  • 1
    Yes, you execute the command but make sure that the command is not invalid both in the application layer and domain.
    – Henrik
    Sep 24, 2011 at 6:27

EDIT: WaybackMachine link: http://devlicio.us/blogs/billy_mccafferty/archive/2009/02/17/a-response-to-validation-in-a-ddd-world.aspx

There's no pat answer.

There are two clear project scenarios which come to mind when I try to answer where validation should live. The first is wherein a DTO layer is used to transfer information between the view and domain layers. For example, you may have a Customer object in your domain layer and an associated Customer DTO in another layer to which you map the Customer information, to then give to the view for presenting Customer information to the user.

The second scenario is a project wherein the entities within the domain layer are shared directly with the view to present the data to the user. For example, instead of maintaining a separate DTO layer and mapping domain object to the DTOs to be given to the view, the view could be given the Customer object directly. So instead of talking via a separately maintained DTO to show a Customer's name, the view would simply ask the Customer object itself for the information.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.