views:

256

answers:

2

I am trying to wrap my head around doing validation in a MVC scenario. I have my application setup so that it has a Data/Repository layer that uses Linq2SQL and creates objects in my domain model. I don't expose my Linq2SQL objects directly to the rest of my app however, for now, my domain model mostly looks like my database tables. I wanted to do this in case I wanted to drop Linq2SQL later.

Then I have a service layer that is called from my controllers to perform actions and grab my domain model from my Data layer.

I want to use a validation framework such as xVal. It seems common wisdom that your model should contain your validation rules. My question is how do you validate part of the model (or various states)? For instance, I have a User object that has username, password and other properties. I have a Login action where I'd like to make sure the Username and Password are provided. However, when I create a new user, I'd want more fields to be required. It seems weird to create a Login object in my model when I already have my User object.

Right now, my Login action is just taking a username and password parameter that are posted to it.

+2  A: 

You're right that validation is usual in the Model layer. The problem is probably in your domain model --- you have an idea of a User that isn't valid until it has all that stuff in it.

Think instead of a User that can be anonymous, or can be filled in. An easy way to think that out is to have User have an instance of a Credentials object; that's also a good place to track permissions etc.

Charlie Martin
This is an interesting way to look at it. Basically, it will show me where I need to pull out parts of my physical model into more of a logical model. This will make it easier to validate part. I'll see how this goes. Thanks!
Jonathan
yeah. The thing to do is to think about the DOMAIN model. Here you have in your "stories" a case where your session can be anonymous; the object model should represent that. Another version would have a Session that has-a User that can be anonymous.
Charlie Martin
A: 

I'm sorry but I cannot think beyond your example. A user object shouldn't have a login method. What I do is have the following

public class User
{
  public bool ConfirmPassword(string password)
  {
    ... 
  }
}

Then a repository. This finds the user by their userName, and then checks ConfirmPassword to see if it is correct, if not it returns null.

public interface IUserRepository
{
  ..other stuff..
  User GetByUserNameAndPassword(string userName, string password);
}

As for validation I usually have 2 ways of getting constraints.

//The constraint itself
public interface IConstraint
{
  string Name { get; }
  bool IsValid();
}

//A way to get constraints that are inexpensive to evaluate, such
//as Name != null etc.  This can be implemented as a service to provide
//custom constraints from an external source (such as rows in a DB)
//which then additionally checks "instance" if it implements the
//interface and adds its constraints to the result too.

//These are the kinds of constraints I evaluated in the GUI every
//time the object changes, so I can show a list of errors.
public interface IConstraintProvider
{
  IEnumerable<IConstraint> GetConstraints(object instance);
}

//Finally a way to get constraints that are expensive to evaluate, this
//includes checking invariants that might involve DB access.  These constraints
//(along with the cheap evaluation constraints) are all evaluated before
//my persistence service attempts to write the object's changes to the DB
public interface IPreSaveConstraintProvider
{
  IEnumerable<IConstraint> GetConstraints(object instance);
}
Peter Morris
I don't have a Login method on my User object. I have a login method in my Service layer. My Repository returns IQueryable which the service layer uses (I know there is some debate about this)
Jonathan