10

I was reading "In MVC should a model handle validation?" because I was curious about where validation logic should go in an MVC website. One line in the top answer goes like this: "controllers should handle validation, models should handle verification."

I liked that, but it left me wondering why we wouldn't do data validation in the View, for several reasons:

  1. Views typically have robust validation support (JS libraries, HTML5 tags)
  2. Views can validate locally, reducing network IO
  3. UI is already designed with data-type in mind (calendars for dates, spinners for numbers), making it one small step from validation

Validating in more than one place is contrary to MVC's concept of isolating responsibilities, so "do it in both" seems inappropriate. Is doing data validation only in the controller truly the dominant approach?

  • The issue here might be one of false dichotomy: there's no reason you can't do validation in multiple places, and thinking of the situation as "either-or-not-both" might be clouding your view (pun!) of this question. Doing some form of client-side validation in a website, for example, can be really useful because users get instant feedback, but it also isn't trustworthy so it can't be the only validation. – Miles Rout Oct 6 '15 at 20:28
10

I don't think there is a single place where you can say all the validation should go. This is because we have a few different competing programming strategies working together in a standard asp.net mvc website.

Firstly we have the idea of separating the domain logic into models, the 'action' logic into controllers and the display into a View. This is based on the idea the all the logic will take place on the server with the browser simply providing a render of the view.

Then, we extend the View by using client side javascript. This is so advanced these days that the 'one page website' idea with Jquery/knockout/angular is common practice.

This practice can be equivalent to writing a whole client side application which itself implements a MVC or MVVM pattern. We denigrate the View to a Data Transfer Object and the Controller to a service endpoint. Moving all business and UI logic into the client.

This can give a better user experience, but you are having to trust an essentially untrustworthy client. So you still need to carry out validation logic on the server, regardless of how well your client pre-validates its requests.

Also, we often have validation requirements which cant be carried out by the client. eg. 'is my new Id unique?'

Any application you create with the goal of giving the best experience/performance will necessarily borrow for multiple programming paradigms and make compromises on them to achieve its goal.

  • 4
    +1 and to emphasize: Never trust the data posted by the client. Ever. – Machado Sep 30 '15 at 18:25
  • How I read this: "validation isn't an isolated concept - all parts of your application need to be validated against one another in different contexts." Makes sense, even if more work. – WannabeCoder Oct 1 '15 at 13:21
  • yes, but also : "you may have two(or more) apps, all following different patterns" – Ewan Oct 1 '15 at 13:39
  • "den·i·grate: Criticize unfairly; disparage." I don't think you're using that word correctly. Good answer otherwise, though. – kdbanman Oct 11 '15 at 19:39
  • no, that's what i meant – Ewan Oct 11 '15 at 19:49
1

Validating in more than one place is contrary to MVC's concept of isolating responsibilities, so "do it in both" seems inappropriate.

Could there be multiple validation responsibilities to consider here? As you said in your #3:

UI is already designed with data-type in mind (calendars for dates, spinners for numbers), making it one small step from validation

So maybe it's:

View: Validate input type, format, requirement...basic user input validation that has nothing to do with the business logic. Catch all this fluffy stuff before we generate network traffic by making a request of the server.

Model: Validate the business concerns of the data. Is that be a legal value according to the business rules? Yes, it's a numeric value (we ensured that in the view), but does it make sense?

Just a thought.

1

I am going to assume you need validation for persistence.

Not only View, but Model should not handle validation either. During my days in IT I realized DDD is one of the ways to ensure you are actually doing things correctly, ie. classes are actually responsible for what they should be.

When following Domain-Driven design, your models include your business logic, and that is it. But they do not include validation, why not?

Let's assume you are already as far that you are using Data Mapper instead of Active Record to persist your domain layer. But still, you want models to be validated, so you add the validation to your Model.

interface Validation
{
    public function validate();
}

class ConcreteModel extends MyModel implements Validation
{
    public function validate() { // the validation logic goes here }
}

The validation logic ensures, you can correctly insert the model into your MySQL database... A few months go by and you decide, you wanna store your Models in noSQL databases as well, databases, which require different validation rules than MySQL.

But you have a problem, you have only 1 validation method, but need to validate a Model in 2 different ways.

The models should do what they are responsible to do, they should take care of your business logic and do it well. Validation is tied to persistence, not business logic, hence validation does not belong to a model.

You should create Validators instead, which will take a model to validate in their constructor as a parameter, implement the Validation interface and use these Validators to validate your objects.

interface Validation
{
    public function validate();
}

class MySQLConcreteModelValidator implements Validation
{
    public function __construct(ConcreteModel $model) { }

    public function validate()
    {
        // you validate your model here
    }
}

class RedisConcreteModelValidator implements Validation
{
    public function __construct(ConcreteModel $model) { }

    public function validate()
    {
        // you validate your model with different set of rules here
    }
}

If at any time in the future decide you want to add another validation method for another persistence layer (because you decided Redis and MySQL are not the way to go anymore), you will just create another Validator and use your IoC container to get the right instance based on your config.

1

For many developers, Fat models against Stupid Ugly Controllers is preferred method.

Base concept in the text is

... So always remember that the Model is not just the database. Even the data you get from web services can be expressed as a Model! Yes, even Atom feeds! Frameworks which rattle off introductions to the Model, almost never explain this upfront which only exacerbates misunderstandings.

and

The View should only be concerned with generating and presenting a UI so users can communicate intent to the Model. Controllers are the orchestrators who translate UI inputs into actions on the Model and pass back output from whatever View has been made aware of the Model(s) its presenting. Controllers must define application behaviour only in the sense that they map user input onto calls in Models, but beyond that role it should be clear all other application logic is contained within the Model. Controllers are lowly creatures with minimal code who just set the stage and let things work in an organised fashion.

The View should only be concerned with generating and presenting a UI so users can communicate intent to the Model is the important part. A model should define de stored data, so it must also be responsible for checking the validity of the data.

When taking the record of a person, each person must have a unique ID number given by the country. This check (generally) is done by the UNIQUE key check by the database. Each given ID number should satisfy some control steps (sum of odd digits should be equal to sum of even digits etc). This types of controls should be done by the Model

Controller is collecting data from Model and pass it to View, or reverse, collect the user data through View and pass it to Model. Any restriction of accessing the data and validating it should not be done by the Controller. It was the Controller who collects the cookie data and it was the Model which checks if it is a valid session or the user have access to this part of the application.

View is the user interface that collect data from user or present data to user. Simple checks can be done by the View like the user input e-mail address or not (thus this can also be done in the View) IMO.

View is the client side, and you should not thrust the user input. Javascripts may fail to run on the client side, a user can use handwritten scripts to alter them or disable the script using the browser. You can set client-side validation scripts, but never you should never thrust them and make the real check on the Model layer.

  • Just to emphasise, the view being concerned only with the UI doesn't mean it can't do some form of validation - providing instant feedback to users when they make a mistake is in fact a really important part of why client-side scripting is useful, in the context of MVC applied to websites. – Miles Rout Oct 6 '15 at 20:31
  • @MilesRout in fact I mean that with Simple checks can be done by the View like the user input e-mail address or not maybe it is not that clear. But what you said is also true for me, simple and easy checks can be done easily in the view. – FallenAngel Oct 6 '15 at 21:49
  • I wasn't disagreeing with you. – Miles Rout Oct 8 '15 at 3:59
0

Views should perform validations for ff purposes:

  1. ) A front end validation can reduce data traffic in your server.
  2. ) it handles invalid data before it can travel in your server.
  3. ) if you want a higher security, a combination of front end and back end Validation is better.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.