5

I am trying to use a combination of Domain Driven Design with Test Driven Development for this application I am building in ASP.NET MVC 3. My archictecture is set up with Repositories, Domain Models, View Models, Controllers and Views. All validation will be handled in the view model. I set up my view model to inherit from "IValidatableObject" so that my validation attributes and my custom validation that i set up in the "Validate" method are both executed when my controller method calls "ModelState.IsValid". The problem I am running into is accessing my repository in the Validate method of my view model. I need to access the repository to check for duplicate records in the database. It seems like the best idea would be to create a property of IRepository type and set that property by passing injecting my repository into the constructor of the view model. For example:

public class UserViewModel : IValidatableObject
{
       public UserViewModel(User user, IUserRepository userRepository)
       {
              FirstName = user.FirstName;
              LastName = user.LastName;
              UserRepository = userRepository;
              UserName = user.UserName;
       }
       public string UserName { get; set; }
       public string FirstName { get; set; }
       public string LastName { get; set; }
       public IUserRepository UserRepository { get; set; }
       public IEnumerable<ValidationResult> Validate()
       {
           UserCriteria criteria = new UserCriteria { UserName = this.UserName };
           IList<User> users = UserRepository.SearchUsers(criteria);

           if (users != null && users.count() > 0)
           {
               yield return new ValidationResult("User with username " + this.UserName + " already exists."
           }
       }
}

Do you guys think this is a good idea?

4
  • Personally I would avoid having a property that performs a database lookup. Commented Sep 28, 2012 at 18:41
  • I see what you're saying, but how else would I validate against duplicate records. I was thinking about creating a custom validation method that the controller method would call and pass in the modelstate. The method would then perform my custom validations and add the model errors to the modelstate (side effect- c# object = pass by reference), but it seems like what i posted would be alot cleaner and code would be simpler. Commented Sep 28, 2012 at 18:50
  • 1
    The Domain Validation must be encapsulated in the domain. Validation is a concept that must be applied at several places in the application. Typically when you validate a View-Model, you are validating to check that the data provided by the user is safe, (apply sanitizer) and apparently correct. Then you usually would call your aggregate root to perform some actions. There you should validate the domain invariants (domain rules). In a CQRS architecture, I have found it's a good practice to validate inside the CommandHandler Commented Sep 28, 2012 at 18:54
  • For more info Commented Sep 28, 2012 at 18:55

2 Answers 2

2

It is good enough but if I were you, I would use

...
private readonly Func<IUserRepository> userRepositoryFactory;
...
public IEnumerable<ValidationResult> Validate()  
   {  
       UserCriteria criteria = new UserCriteria { UserName = this.UserName };  
       using(var UserRepository = userRepositoryFactory())
       {
           IList<User> users = UserRepository.SearchUsers(criteria);  

           if (users != null && users.count() > 0)  
           {  
               yield return new ValidationResult("User with username " + this.UserName + " already exists."  
           }  
       }
   }
Sign up to request clarification or add additional context in comments.

1 Comment

In your first post, it sounds like I shouldn't follow this approach. It seems like you are saying I should only put business logic validation in the domain.
0

You can add Domain Service class to get object match with your criteria and validated at domain service level

 public class PurchaseOrder
    {
        public string Id { get; private set; }
        public string PONumber { get; private set; }
        public string Description { get; private set; }
        public decimal Total { get; private set; }
        public DateTime SubmissionDate { get; private set; }
        public ICollection<Invoice> Invoices { get; private set; }

        public decimal InvoiceTotal
        {
            get { return this.Invoices.Select(x => x.Amount).Sum(); }
        }

    }

    public class PurchaseOrderService
    {
        public PurchaseOrderService(IPurchaseOrderRepository repository)
        {
            this.repository = repository;
        }

        readonly IPurchaseOrderRepository repository;

        public void CheckPurchasedOrderExsist(string purchaseOrderId)
        {
                var purchaseOrder = this.repository.Get(purchaseOrderId);
                if (purchaseOrder != null)
                    throw new Exception("PO already exist!");
        }
    }

2 Comments

It seems like you are saying, I should validate my form in the view model, but business logic validation should go in the domain or service which makes sense. The question is, how would i send validation errors back to the modelstate in the controller?
you can do this by throwing exception from domain model and catch that in view because as per DDD your domain model should be isolated from your infrastructure logic...

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.