Where is the best place in an app to do validation? Rules of thumb?
Each module should do its own validation and never trust what the calling code gives it. This typically means that validation should happen at each layer of your application. You especially do not want to trust any validation to occurs on the client side, because that can lead to security holes. Code that runs on the client has been known to change from time to time.
If you're doing MVC, chances are you're working from the ground up using TDD.
I'm not sure if this is the best way, but the way I do things is..
- Make my business objects.
- Define some kind of validation framework, so business objects can return a list of errors on it's current state and test those using unit testing.
- If you're using linq to sql, implement the partial method OnValidate() and make it so it calls your mybusinessobject.geterrors(). OnValidate is called when you do db.submitchanges() so you can stop invalid data getting saved
- Now, in your controllers, when someone makes a new business object, or edits one, make the object with whatever data you get from the user - then call your geterrors() method and do whatever
- Then client side validation if you can be arsed
That is a framework which scott guthrie described here: http://weblogs.asp.net/scottgu/archive/2008/09/02/asp-net-mvc-preview-5-and-form-posting-scenarios.aspx
I like it and it means you can define your business rules once and re-use them on different layers, which means its less likely you'll miss them out at a particular area when you are updating things
As a rule of thumb, as you said you should validate as early as possible, but in client-server applications, it's important to validate data as soon as possible on the server to prevent security problems that might arise.
I think you should validate three times.
- in the client, 2 on the server and 3. in the database with a check constraint.
In a console application you can validate immediately because you know in what order the user will enter the data.
I like validating after the user clicks Ok or Next - before they leave the screen they are on. Validating during modification rarely works - the user has to be able to backspace, insert in a string as they enter it, and a copy/paste into a string field has it's own issues. If the string is colored red until it's valid, that might help, but you still have to prevent proceeding until it's corrected. Similarly for leaving the textbox, it can be jarring to have message boxes show up while doing data entry. Wait until the user says everthing is done, and do all the validation at once.
I liked Timothy's picking up on MVC.
Since we are given very little about the nature of the application, I want to point out some very general rules of thumb along with the good advice already provided.
Validate in a way that
No irreversible action is performed with invalid input
The user does not lose work
The user's activity is never put in a state where an erroneous input cannot be easily identified and simply retracted
The application will not fail or crash
No (shared) persistent material is ever left (or seen) in a bad state as a result of application handling of invalid data
An user is not frustrated in accomplishing their useful work as a result of how and when validation is done
That should pretty much cover it.
Depending on how the application progresses you can validate either before you leave that page/step (if its like a wizard where you step through multiple pages/steps), or you can have it validate immediately once the user leaves that textbox/value. Another option is validation while it is modified.
There are a lot of great answers here about general best practices... but your question specified "MVC", and there is only one right answer for that.
EDIT: Your "question" didn't say MVC, but your tags did.
MVC = Model View Controller
All business logic goes in the Controller. That's the answer.
The other answers in this post are great tips, such as "don't trust client validation"... and "validate everywhere".
One other tip: validation everywhere is a lot easier to do if you can define your validation rules in metainformation that all of your validation logic can interpret. Then you only need to define the rules in one place, and you don't have to worry about your client-side validation, server-side validation, and test cases getting out of sync with each other.