Thursday, April 29, 2010

Validation Considerations

The post stems from a conversation I had yesterday with a guy who is learning ASP.NET.  The question was when to validate client-side vs. when to validate server-side.  More over, when to validate in code vs. inside the database.

One of the cool things about .NET and SQL is that it lets you do things pretty much any way you want to suit your needs.  At the same time, it can leave people who are new to the technology feeling lost.

While there is no steadfast rule on how to do validation, I will run through a few scenarios where I might choose to do validation one way over another.  A good indication that you need to re-work your validation is if you're sending a lot of data to the client or making a lot of roundtrip calls to the server (be it a web server or database server, etc).  It seems like an innocent thing but there is a finite amount of things a computer can do in a given period of time and only so much space in which to transmit the inputs and outputs of that work.

Client Side Validation

Client side validation is most likely going to get to the client in the form of scripting, probably JavaScript.  That means a larger payload coming down the wire with the page.

In my opinion, the validation script should be small, relevant, and require no additional data from the server.  You might also argue that the script's execution shouldn't be critical to the success of the operation. What I mean by that is if the client has scripting disabled, it shouldn't prevent the user from being able to use the application.  I'll talk about what to do in this case momentarily.

Examples for good candidates for client side validation scripts:  verification of a birthdate (is it before today's date, are you older than 18 or 21), validation of SSN format (9 digits, all numeric), or validation of email address format (several characters and @ sign and a dot with a valid extension).

Notice all of these are validations of raw user input which is also a good indication that you might want to use client side scripting.

What to do if scripting is disabled?  In my opinion, client validation should assist but not replace validation within your business objects.  If scripting is disabled and invalid data is sent across, the business objects themselves shouldn't allow the data to be saved.

Two ways you could handle this...
1. Thrown an exception within the object, and provide a text area on the screen where you display error messages.  (Keep in mind you may only want to display these validation exceptions and make sure that any other exceptions display a generic "This operation cannot be completed at this time." message for other exceptions).
2. Create an IsValid method in your objects that return a bool value and take an out parameter for a list or string of errors.

Technically, you could also do some checking inside a stored proc before writing the data to the database.  However, I believe that the database should only do validation in limited scenarios which I've included below.

Server Side Validation

Keep in mind you can mix and match validation.  And while you can do all your validation server side it is an expensive operation to keep sending entire pages to be parsed, data to be evaluated, and new data to be sent across the wire.  From the time, load, and bandwith prespective, server side validation has really become less common in favor of client side validation.

I put AJAX in the server validation group because while you do have some scripts that come down like a client-side validation, you are really putting the burden on the server to do the work and then updating the client accordingly.  This is a valid way of doing validation but again for simple validation the client side validation may be the way to go.

I would definately use AJAX to do validation in cases where you don't have the data you need client side or the validation is intensive and/or time consuming and shouldn't bog down the user machine.

You might also do straight up server side validation (posting a page back to the server for processing) in cases where say you've completed a form and you can't really do anything else until the page data has been processed and some action(s) taken.

Examples for this scenario: A registration form or login page is a good example of this.  But as I said, you could use AJAX to silently do the submission and update the UI accordingly.  But more than likely, unless something fails, your going to want to redirect or render a new page which is a server side thing anyways.

You would also do server validation in cases where you have a lot of different pieces of data (objects) that don't make sense to push to the client. 

Example for this scenario: Say your application allows you to apply for a loan.  You're client script has validated the data being entered but now its time for you to do some credit checks.  It doesn't make sense pull the credit data, transfer it to the client, and have a script that processes the credit report.  You'd want to do that on the server, maybe save it to the database, and then return the results of that credit check back to the client either in the form of a new page or maybe AJAX is polling silently so it can display an APPROVED or REJECTED message.

SQL Validation

The last part of the validation puzzle is SQL itself.  Technically, you could do zero validation on the client or in your objects and throw errors from your SQL procs if data was invalid.  Its data, its going into a database, and the database should be responsible for making sure the data it contains is valid, right?

Yes, but to a point.  With one notable exception, the database should really only be validating data type, relationship, and constraint type information.  Basically, anything that would break the database schema.  Business rule/logic data should probably be outside the database; again, with one notable exception.

Take the case of the social security number.  The database should only care that the SSN meets the requirements of its field in a table (say a non-nullable integer), but it shouldn't parse the SSN to determine if the numbers are valid, if its the right number of digits, etc.  That is business logic!

Exception:  The notable exception on when to use the database for validation is in situations where its not feasible, practical, useful to do the validation outside the database.

Example:  Say you have a registration form and the username is an email.  You want to make sure the email doesn't already exist (IE, an account doesn't already exist).  You're not going to send all your account emails to the client to validate; that's not practical or secure and might take a long time.  So you you make an AJAX call to the server.  More than likely, you're not using server memory to store all the emails.  Plus, its not practical to load all the emails into an object and iterate through them in code just to see if one exists.  In this case, the database is really the prime candidate to do this work.  The database is born to these types of queries.  So you call a proc that would search the user table for that email and return a value to indicate if the email already exists or not.

Another flavor of this is cases where you are doing data manipulation that is more of a data operation than an execution of business rules.  There might be some business logic but primarily the goal of the operation is to generate some type of data.

No comments:

Post a Comment