I was wondering where exactly we should put input validations(imagine an API call send input to apply free times of a user). Is it right to inject validation class in service Layer and call validate method inside service? or it's better to put it in the infrastructure layer or even in Domain model? I just wanted to see a sample code that's implement validation of input for an API in Domain-driven design approach? what if I use CQRS architecture?
-
1I suggest you to read my answer on a similar subject here: https://groups.google.com/forum/#!msg/dddinphp/GwXTDn_Df_0/WvhiTatB3GcJ – Boris Guéry Oct 12 '18 at 17:07
5 Answers
I use in my DDD/CQRS project following approach, structure of a project is API layer, Domain layer, Data Access layer, all input data from UI or from User are validated before, command are created and dispatched, to update the state of Domain, and we validate input data two times one is on the UI, (Angular app), and second one in Web API layer, if the data are valid the CQRS command are created and dispatched after that you can have Business logic validation. For validation you can use FastValidator or FluentValidation
UPDATE: Here is the simple example we have API for Create Batch Entity.
[HttpPost]
[Route("create")]
public IHttpActionResult Create([FromBody] BatchEditModel model)
{
var createCommand = model.Map<BatchEditModel, CreateBatchCommand>();
var result = (OperationResult<int>) _commandDispatcher.Dispatch(createCommand);
return Result(result);
}
As you can see as user input data will be BatchEditModel
.
so we have BatchEditModelValidator
which contains input data validation:
public class BatchEditModelValidator : AbstractValidator<BatchEditModel>
{
public BatchEditModelValidator()
{
RuleFor(x => x.Number).NotEmpty()
.WithMessage(ValidatorMessages.MustBeSpecified);
RuleFor(x => x.ClientId).GreaterThan(0)
.WithMessage(ValidatorMessages.MustBeSpecified);
RuleFor(x => x.EntryAssigneeId).GreaterThan(0)
.WithMessage(ValidatorMessages.MustBeSpecified);
RuleFor(x => x.ReviewAssigneeId).GreaterThan(0)
.WithMessage(ValidatorMessages.MustBeSpecified);
RuleFor(x => x.Description).NotEmpty()
.WithMessage(ValidatorMessages.MustBeSpecified);
}
}
this Validator will be executed before BatchEditModel will be mapped to CreateBatchCommand
and in CreateBatchCommandHandler
we have Business logic validation CheckUniqueNumber
public OperationResult Handle(CreateBatchCommand command)
{
var result = new OperationResult<int>();
if (CheckUniqueNumber(result, command.ClientId, command.Number))
{
if (result.IsValid)
{
var batch = _batchFactory.Create(command);
_batchRepository.Add(batch);
_batchRepository.Save();
result.Value = batch.Id;
}
}
return result;
}

- 4,071
- 2
- 23
- 34
-
Web API layer you mean before controller? or the service layer? – Alireza Rahmani Khalili Oct 11 '18 at 17:30
-
1@AlirezaRahmani no it is exactly controller layer, you should keep User input validation in this layer, and business logic validation into Business layer – Sergey K Oct 12 '18 at 21:21
-
1@AlirezaRahmani I've updated the answer with example to be more clear – Sergey K Oct 15 '18 at 14:20
-
How do you go about validating the client ID exists (presumably in the database)? I noticed it isn't part of your AbstractValidator. I have a similar scenario and I'm torn between adding it in the AbstractValidator, in the command handler or in the domain model :'( – heymega Apr 08 '19 at 16:15
-
1@heymega I assume you want to update an existing client data, user set changes on the UI, and then click Save button, and the command with clientId will be posted in command Handler you can use repository to retrieve the entity by clientId posted in command if there is no client with such Id I will throw an exception, because it is an exceptional case, if client found the you can apply validation and other business logic!!! – Sergey K Apr 10 '19 at 16:25
-
I see one problem with this approach where you only validate in the API layer. What if you decided to ditch the API & instead use this in the Xamarin Project, meaning this approach will make it difficult to decouple the presentation layer from domain layer, as your domain is left open for invalid entities being created. – Kishor Tiwari Nov 15 '22 at 16:59
My approach is putting validation in the domain model, I validate the functionality of aggregates, entities, value objects, etc.
Then you can validate application services too, and user interface too. But those validations are a plus, a validation enhancement from the user point of view, as validation is faster.
Why this duplication of validations at different layers? Well, because if you just rely on UI or application service validations, it maybe possible that if they don't work well for whatever reason, and you don't validate the domain model, you are executing domain functionality without validating it.
Also, I would point out that not all the validations can be done at UI or at application layer, because you may have to access domain.
Finally, doing CQRS or not is independent on where you decide to put the validations. It's just that if you do CQRS, then validations at application layer are easier to do, as you can put them in decorators that wrap commands and queries.
Hope my explanation helps.

- 4,470
- 2
- 28
- 48
-
There is no need to put User input validation into Business Layer in this layer should be business validation – Sergey K Oct 12 '18 at 21:23
-
@Serghei if data bypass imput validation and reach domain model, it becomes business validation. Eg checking a string field length at the UI may become in checking the length of the argument of an entity constructor. I check it at both places, the ui form and the entity constructor – choquero70 Oct 12 '18 at 22:43
-
I would recommend to validatio User Input Data on both sides on th UI and in Web API on the back end, before the corrupted data will rich the domain layer. – Sergey K Oct 15 '18 at 14:13
-
2@Serghei but what if due to a bug or whatever reason, those validation don't work as expected? Then the corrupted data will reach the domain though we didn't want to. That's why I put it in the domain too (defensive programming, Red Book, page 210). From my point of view, domain model shouldn't rely on nor assume that higher layers have done the validation. Domain model should validate the data that it receives. Anyway, it is just what I do and it is my recommendation. Regards. – choquero70 Oct 15 '18 at 16:08
-
if you have a bug or validation not working as expecting there is no matter where it will be placed, yes you are right Domain Model should throw exception if someone what to corrupt data but throwing exception is not validation. It could be approach that you validate everything twice in API layer and Domain Layer, I would prefer to throw exception, but it is up to what you and to get in result, both approaches could exists, – Sergey K Oct 15 '18 at 17:32
-
In Entity constructor I will throw exception if some one use this entity in wrong way. – Sergey K Oct 15 '18 at 17:53
-
1@Serghei what I do in domain model is to through exception too. I know that throwing exception isnt validation. Validation is checking some condition about the data, where you can use specification pattern (predicates). Throwing exception is the action you take as a result of validation. Another alternative instead of throwing exception would the notification pattern if you can collect several errors. – choquero70 Oct 15 '18 at 18:41
where should put input validation [in Domain Driven Design]?
This is largely unrelated to DDD, but: the closest possible to the input source.
You aren't going to wait until invalid data has crossed 4 layers to discard it.
Input validation precisely means you don't need anything else (e.g. loading other data) to check it, so you might as well do it as soon as you can. Of course, caveats apply, like any validation that can be circumvented must be double checked - client side javascript for instance.

- 13,738
- 1
- 32
- 51
-
it's better to place it before controller, in a controller or in a service layer? – Alireza Rahmani Khalili Oct 15 '18 at 13:12
-
1I do it both client side and in a controller. Many front end/web frameworks have helpers or systems that allow you to do input validation easily, sometimes just by tagging fields on your data structures. – guillaume31 Oct 15 '18 at 13:14
what if I use CQRS architecture?
I wouldn't expect CQRS to change things very much.
Usually, by the time you are invoking a method in a domain entity, your inputs should have already been converted from their domain agnostic form into value objects.
Value objects are expected to be constructed in a valid state, and often include a check of a constraint within the constructor/factory method that produces it. However, in Java and similar languages, the implementation of the constructor usually throws (because constructors don't have any other way of reporting a problem).
Often what clients want instead is a clear understanding of all of the constraints violated by the input data, rather than just the first one. So you may need to pull the constraints out as first class citizens in the model, as predicates that can be checked.

- 52,766
- 5
- 49
- 91
-
You mean I should inject the validation class in my model? @VoiceOfUnreason – Alireza Rahmani Khalili Oct 11 '18 at 15:11
-
You should validate in your app service before attempting to modify your domain. Validation should be towards the edges of your app (but not in the UI) so invalid or incomplete requests aren't even getting into your domain model.
I consider it two levels of validation because you will validate the request before attempting some behavior on the model then the model should again verify for internal consistency, since it can never be persisted in an invalid state.

- 41
- 7