First, you need to step back and take a lager picture of what you are doing.
The purpose of the domain layer is to model your business concepts using OOP, and implement business requirements checks to ensure your service integrity, business-wise. All operations in that layer are application independent and should execute in any piece of software related to that domain.
The presentation layer, on the other hand, is responsible for mediation between customer facing interface of a specific application, and this application's other layers. Frameworks such as asp.net webapi hide some cross cutting concerns such as authentication, and does serialization/deserialization for you, so you are left with less code to write for this layer.
Put another way, the presentation layer is responsible for enforcing your interface specification, and your domain layer is responsible for enforcing business requirements. The relevant object models for these two might differ, which is why you may have conversion operations, and presentation level validation may not suffice to enforce business invariants.
Now, where to validate ? The answer is quite straightforward. If your validation is a business requirement (I cannot send an email from a malformed email address, whatever the application), then this validation should happen in the domain layer. If the email formatting is a requirement in your interface specification (EmailsController
expects CreateEmailMessageDTO.Email
conforming to RFC), then validation should happen in the presentation layer.
Business requirements should never depend solely on presentation layer validation, otherwise business integrity depends on interface specification, violating the single responsibility principle (SRP) and DDD principles (domain validation happens in the domain layer only). But what if the validation is both a business requirement and an interface specification ?
You basically have two options :
- implement in business layer only
- implement in both layers
Implementing the validation in business layer only is obviously cheaper and easier, don't-repeat-yourself (DRY) approach, as you need to write less code, so your application is smaller, easier to understand and maintain. Your presentation layer does not need to validate because the domain layer will do that for you, just think of that as a delegation. The drawback is that, sometimes, business layer validation can happen quite late in the request life-cycle. You will eventually need to query business data from the persistence layer before being able to validate your business state. In this situation, it's up to you to decide whether you prefer to fail early by adding a presentation layer validation or keep the code smaller.
In your situation though, the additional cost of adding email format validation in the presentation layer is very small, both at the code maintenance level and the runtime execution footprint level. Doing both validation seems acceptable, unless you are in a specific context, such as very high throughput low available memory, which might advocate for smallest footprint over maintainability. However in such situation you might reconsider your overall architecture, but that's another topic.