It seems that I always appear to run into this issue when performing code reviews. As has been well documented in various locations on the web - all input is evil, until proven otherwise. Some people attempt to mitigate this risk by providing dropdowns or calendar controls to coach our users into entering the right values. While this works often, it is still coaching the users and should not be seen as a replacement for solid validation of the user entered data.
For example, imagine you have a textbox control on a page that is supposed to accept a Date value. To "coach" the users into entering an appropriate value, you provide a calendar popup control. Now, when the data has been posted back to the server to be stored in the database, do you:
A) Assume that because we have given the users a calendar popup control, their input will be exactly as you might expect.
B) Perform some additional validation that the textbox has a value entered. If there is a value, assume that it is entered correctly.
C) Imagine that there really isn't that calendar aid and validate the input as if it were entered entirely by hand by the users themselves.
If you answered "C", congratulations, you are correct. The fact is, although we provide those wonderful entry "aids" to assist our users, they will never guarantee correct input. Here is the wrong way to do it:
Dim dateValue as DateTime
dateValue = Date.Parse(me.txtDateInput.Text)
What happens if the Date Input textbox comes across as an empty string? You will get a big fat exception. Now, in .Net 1.1, there were certain methods that you would code to validate input - or if you were using VB, you could use one of the methods in the wonderful Microsoft.VisualBasic namespace. In .Net 2.0, though, there is a wonderful additional method to each one of these primitive objects.... "TryParse(....)".
This is really a great little method that takes as input 2 parameters:
- String representing the value to parse.
- DateTime/Integer/etc. representing where to store the final value - if the input could be parsed.
The great thing about this method is that it will actually return a boolean value if it could successfully parse the value. Therefore, using this new method, the code above could be amended as follows:
Dim dateValue as DateTime
If Date.TryParse(me.txtDateInput.Text, dateValue) Then
'// Input is valid. You can use the dateValue
'// variable safely.
Else
'// Input in NOT valid. Please direct the user to
'// enter a value correctly.
End If
Really powerful! Here's another example - using values obtained from a QueryString as the offending code:
Dim id As Int32 = -1
If Request.QueryString("id") IsNot Nothing Then
id = Int32.Parse(Request.QueryString("id"))
End If
This looks good, right? It does - and it might even function correctly about 70% of the time. What about that other 30%, though? What happens if a user decides to mess around with the QueryString values? Instead of a number, they decide that it should be a text value instead. Exception! Using the TryParse(...) methods, though, you can do something nice and easy like this:
Dim id As Int32 = -1
If Not Int32.TryParse(Request.QueryString("id"), id) Then
'// Notify user of invalid querystring value.
End If
This is nice, clean and efficient - plus, it has the added bonus of handling the situation where the QueryString ID value returns nothing.
Really powerful!
These are just the basics on input validation (and I can go on and on and on), but I think you can see my point.
Enjoy!