I am wondering what is the best way to do a database constraint check (for example, UNIQUE) in an ASP.NET MVC application, build with DDD in mind, where the underlying levels are Application Layer (application), Domain Layer (domain model) and infrastructure level (logic) sustainability, logging, etc.).
I looked through a lot of DDD samples, but many of them do not mention how to do validation in the repository (I believe that this type of validation is suitable here). If you know any samples, do it, please share them, it will be very appreciated.
More specifically, I have two questions. How would you do the actual check? . Would you explicitly check if the client name exists by querying the database, or would you try to insert it directly into the database and catch the error if there is one (it seems randomly)? I prefer the first one, and if you choose this, should it be done in the repository, or will it be the work of the application service?
When an error is detected, how do you pass it on to ASP.NET MVC so that the user can be well informed about the error? It is preferable to use ModelStateDictionary
so that the error is easily highlighted on the form.
In the N-Lyered application from Microsoft Spain, they use the IValidatableObject
interface, and the simplest property check is placed on the object itself, for example:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { var validationResults = new List<ValidationResult>(); if (String.IsNullOrWhiteSpace(this.FirstName)) validationResults.Add(new ValidationResult(Messages.validation_CustomerFirstNameCannotBeNull, new string[] { "FirstName" })); return validationResults; }
Before the object is saved, a Validate message is called to verify that the properties are valid:
void SaveCustomer(Customer customer) { var validator = EntityValidatorFactory.CreateValidator(); if (validator.IsValid(customer)) //if customer is valid { _customerRepository.Add(customer); _customerRepository.UnitOfWork.Commit(); } else throw new ApplicationValidationErrorsException(validator.GetInvalidMessages<Customer>(customer)); }
An ApplicationValidationErrorsException may be detected in the MVC application, and validation error messages can be parsed and inserted into ModelStateDictionary
.
I could add all the validation logic to the SaveCustomer method, for example. requesting a database check if the client already exists using this column (UNIQUE one). Perhaps this is normal, but I would prefer that validator.IsValid
(or something similar) do it for me or this check is again performed at the infrastructure level (if it is here, I'm not sure).
What do you think? How do you do this? I am very interested in getting more information about the various validation methods in layered applications.
Possible Solution # 1
In the case where the validation logic cannot be performed in the presentation layer (as suggested by Iulian Margarintescu) and must be performed at the service level, how would you pass validation errors to the presentation level?
Microsoft has a suggestion here (see list 5). What do you think about this?