views:

54

answers:

1

I'm trying to use xVal to validate the registration of a new user. I've ran into a buzz saw when trying to implement the logic that checks to see if the user name that the new user is trying to register with is already taken. I can't seem to find a way to accomplish this without having my User entity have a dependence on my UsersRepository. Here's the method I need to find a way to implement in the my User Entity:

public IEnumerable<ErrorInfo> ValidateUniqueUserName(string username)
{
    if(usersRepository.Users.Exists(m => (m.UserName == username)))
        yield return new ErrorInfo("UserName", "User name already exists");
}

Any ideas on how I can continue to use xVal for this scenario and keep my User entity decoupled from my UsersRepository?

+1  A: 

DDD would suggest that you might have a Domain Service to abstract the Users repo from the domain validation (invariant enforcing).

I'd like to know where the code from your example above resides (validation service)? But i'd suggest you make sure it is in the domain. Here is a clever way to attach complex validation to entities that still support the IDataErrorInfo interface.

What i would suggest is an Domain Service within your validation method that returns your Users.Exists query. Something like:

        base.AddRule(new ValidationRule()
        {
            Properties = "username",
            Description = "User name already exists",
            validator = () => !(new UserService()).Users.Exists(m => (m.UserName == username))
        });

In the example above i will be using DI to inject the appropriate dependencies into the UserService for accessing of the repo/data but you could use a factory or manual DI object creation method if you like:

        base.AddRule(new ValidationRule()
        {
            Properties = "username",
            Description = "User name already exists",
            validator = () =>
                {
                    UserService us = ObjectFactory.GetInstance<UserService>();
                    return !us.Users.Exists(m => (m.UserName == username));
                }
        });

NOTE: The above method requires the validator property to be set to false to indicate an invalid state (in case that wasn't clear).

cottsak
Yeah, I think I need to do a bit of research and implement a pure DDD approach here. I'm not sure if you're familiar with xVal but as per the xVal example the above code actually resides in the User class. I thought about moving the validation functionality to the repository (don't have a service layer) but then my repository gets very complex. It sounds like I need a good service layer but I'm not sure where to start
DM
I should be clear: i use xVal too in my asp.net-mvc project but only to return errors for the indexer required by the `IDataErrorInfo` interface. I'll assume ur doing the same thing. With my example above, i have removed the need for the xVal library cos my own code returns errors itself. Study the linked SO question above. My validation code lives in the entity class too (where it should i believe, not in a service).
cottsak
See the thing is, when i discovered how little of the xVal code i was using, i realised that i didn't need it. The only code i used i think was the `ErrorInfo` class that i see you use as well. All you need to do is have your entity classes implement `IDataErrorInfo` properly and MVC will understand how to validate. It's really quite easy. My code examples show how - http://stackoverflow.com/questions/1721327/validate-object-based-on-external-factors-ie-data-store-uniqueness/1741831#1741831
cottsak
Very thourough and enlightening. One thing I do really enjoy about xVal is the client side inclusion with jQuery Validate. Is that difficult to include in your implementation?
DM
If i am not mistaken, the jQuery client-side validation hooks directly into the `IDataErrorInfo` interface. So given that it's supported, you shouldn't have a problem.
cottsak