neminem
neminem

Reputation: 2698

Can you validate a model instance using properties from its controller?

Supposing I had, by way of demonstration, a controller that looked like this:

public class ProjectController : Controller
{
    private IProjectRepository projectRepository;

    public ProjectController()
    {
        DBContext context = new DBContext();
        this.projectRepository = new ProjectRepository(context);
    }

    public ActionResult Create(Project project)
    {
        if (ModelState.IsValid)
        {
            // do whatever
        }
        else
        {
            return View(project);
        }
    }
}

And suppose that this was the controller for a model that looked like this:

public class Project : IValidatableObject
{
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        // this is where I would like to add code
    }
}

My question is: is there really no way in the validation code to reference the projectRepository object on the controller? Yes, I could technically add quasi-validation to the Create() function on the controller, do the check there, and add errors directly - but in the real case, there are a number of actions that would all perform the same validation, which is really tied to the model you're trying to create (or edit, or copy, or whatever else). But it's tied to the model and to other existing instances of the same model, which only the controller knows how to query for. Is there any way to get around that?

(The goal is to check that the current model object under validation isn't the same as one that exists already; I'm open to other suggestions of how to do that as well, it just seemed like it clearly should be a job for standard validation code, either using IValidatableObject or using a ValidationAttribute. But I am not an expert in .net MVC validation, or for that matter, .net MVC at all.)

Thanks!

Upvotes: 0

Views: 275

Answers (3)

Ronald
Ronald

Reputation: 1542

You might be better of putting your validation in the service layer

The online scaffolding tool CamoteQ generate its model validation code this way, which is a good reference for self-study.

Upvotes: 1

Keith Payne
Keith Payne

Reputation: 3082

IMO, there is a bit of a convention issue at play. The model that the controller returns to the client is a ViewModel, not an entity. This comes into play when thinking about which objects have knowledge of dependent objects.

The repository deals with models (entities), and the controller deals with ViewModels. ViewModels are really just a bunch of data and formatting, so set-level validations don't make sense on a ViewModel.

And really want the business-layer or repository to perform set-level validation, not the model itself. You could set a reference to the repository on the model when it is created and have the model call the repository for set-level validation. But this becomes problematic when you want to clone or deserialize the entity.

By the way, EntityFramework solves these problems by allowing you to Attach a disconnected entity. You might want to use EF instead of the repository pattern.

But for you immediate issue, I would not try to perform set-level validation from within the entity or viewmodel.

Upvotes: 1

Mister Epic
Mister Epic

Reputation: 16743

IValidatableObject belongs to the DataAnnotations namespace. To my mind, Data Annotations are great for input validation. Where they start to fall down is when you start applying complex business rules where your domain model's validity depends on the state of other domain models.

When that happens, introduce a service layer. Put all your business rules in there, and allow the service to mediate the conversation between your models. At the end of the day, a service is supposed to be the interface with which you communicate with your model.

This is where I usually say to myself, "Hey, your app has now reached the 'medium-complexity' stage"! :)

An older but still relevant tutorial can be found here: http://www.asp.net/mvc/tutorials/older-versions/models-(data)/validating-with-a-service-layer-cs

Upvotes: 3

Related Questions