views:

479

answers:

2

I'm trying to validate user input, in particular user passwords. I have some jQuery validation, but of course I also need to validate on the server side. Now my request comes in to the controller, which will hand it off to a UserService. Everything is loosely coupled, so the controller really doesn't know too much about the inner UserService. Now suppose the user entered a weak password so I need to tell him "hey, that is insufficient."

Question is: What is the best way to do this?

Somehow, I need to be able to call

ModelState.AddModelError(field, exception);

in order to indicate what went wrong, where and why - in the simple example I already know it's the password because it is really the only field on the form, but in general this is not so easy. Now I was close to writing my own Exception type to do something like

ModelState.AddModelError(ex.Field, ex.Message);, where I might need some additional mapping - which is essentiale the path taken in NerdDinner where they have RuleViolations.

However, in NerdDinner, the business object is self-validating. This doesn't seem to be the best way in this case, because the 'business object' here is really just a store for email and password that implements IIdentity. It shouldn't know anything about password lengths and should be reusable across different applications.

Moreover, ArgumentException and ValidationException don't seem to fit either because the first is made for contract violations and the latter is to be used by DataAnnotations.

All this is just the tip of an iceberg of course, because there are so many subtleties lurking around. Perhaps someone can point me in the right direction?

+1  A: 

You can use xVal.

Dmytrii Nagirniak
Thanks, this looks promising, I'll have to look into that in greater detail.
mnemosyn
+1  A: 

If I understand correctly you want to validate whether the user password is sufficient or insufficient. If you aren't using self validation on the object itself then can I suggest you put a validation method on your user service.

...
var result = userService.Validate(newUser);
if (!result.IsValid) {    
    result.Errors.ForEach( m => ModelState.AddModelError(m.field, m.message));
}
...

How about that?

The only issue with this approach is that to access any validation around the User object you'd have to pass it into the userService, which may or may not be what you want to do.

Answer to comment below:

Well you would have to create a ValidationResult, something like.

public class ValidationResult
{
   public string Field {get;set;}
   public string Message {get;set;}
}

So if I'm reading correctly, your Controller has a UserService, the UserService has a Validator, and the Validator validate the User.

As you pass this validation up from your Validator to UserService to Controller, just intercept it and use it, then pass it along.

If you don't want to role your own validation library (and you shouldn't) there are some great tools like Enterprise Library and FluentValidation. They can separately define your validation logic external of your objects if that is what you are concerned about.

Khalid Abuhakmeh
Thanks for the answer. I was a bit imprecise in my question I'm afraid: The `UserService` will delegate parts of the job even further, so the same problem will then appear in the communication of `UserService` to the actual validator. More importantly: What type of object is returned by `userService.Validate();` in your code? This means I'd have to self-bake this, right?
mnemosyn