Procrastination will only get you so far before you have to finally just put it off and get your ass to work. Today I finally get back into the swing of things with my first post since my sites (still incomplete) migration to SiteFinity Content Management System. I know there is still much to do with existing content, like fixing broken links and all that nonsense, but I’m taking a positive, constructive approach and getting things started with a revival of my now merged Software Blog. Today we talk about validating input parameters for the asp.net objectdatasource control.
As you likely don’t already know, I’ve just recently launched the new City of McAllen Website (a post on the impact this opportunity has had on my life is coming soon), and in one section in particular, I needed to make use of the QueryString to input parameters to an ObjectDataSource for selecting specific items from our Database. Straightforward enough yes?
The problem is that I did not have any way to validate input to ensure that the parameters were of the correct type. Of course I made use of stored procedures and strongly-typed parameters to ensure that invalid input isn’t processed. However, these only prevent bad code from executing, and don’t actually do anything to prevent an invalid argument exception if users make an error (or worse, attempt to inject malicious code, the bastards). As a result, if the QueryString does not resolve automatically to the expected type (in this particular case Int32), an exception is thrown, and the user is shown a generic error message. Not very user friendly for a city that prides itself on its high levels of satisfaction from its citizens!
The simplest solution to implement seemed to be to check the querystring on Page_Load, which for all practical purposes should have worked just fine. This particular page, however, has multiple uses, and does not ALWAYS require a querystring. So I would have to account for this situation when checking, first verifying that I’m the correct mode before validating the querystring. Not only does this add overhead to the implementation cost, but it isn’t practical, since the querystring isn’t coupled to the Page_Load, it is coupled to the input parameters of the ObjectDataSource, so it is there that the validation should occur.
Naturally, this lead me to the ObjectDataSource’s OnSelecting event, which occurs right before the datasource Select Command is executed, a natural place to perform validation! Using the now famous Int32.TryParse, it’s a no-brainer to ensure that the requested parameter is an integer:
if (!Int32.TryParse((string)e.InputParameters[“ID”], out bID))
e.InputParameters = bID;
As you can see, the input parameter is checked for validity, and modified if it doesn’t resolve to an integer. Additionally, since on failure, Int32.TryParse resolves the output integer parameter to a zero, I can use this as a dummy value to ensure that the FormView to which this ObjectDataSource is attached renders the EmptyViewTemplate, informing the user that the requested item could not be found. Much more informative and user-friendly than some random “OOPS” message!
Unfortunately, this didn’t work! At least, not yet. When I tested the page, passing an invalid, non-integer in the querystring, the page continued to throw an exception, showing that the input string was not valid. I knew that I was handling the validation in the right spot, and I knew that it should resolve all input to a valid integer, 0 in the case of an error… However, running the site in Debug mode, I discovered that the OnSelecting event wasn’t even firing! Something was definitely wrong here… of to The Google I went…
Interestintly enough, the first link I found was to a great article by Erwyn Van der Meer on this very subject, reaching the exact same conclusion as I did. Confident that I was at least on the right track, I reviewed his article to find where I might have gone wrong…
I didn’t find the explicit reason for why things weren’t working, but something Erwin wrote caught my attention:
…you can even specify that a parameter should be of type Int32, but the page crashes nonetheless.
This immediately reminded me that I had declared the QueryStringParameter to explicitly be Int32. This means that the ObjectDataSource itself automatically expects and assumes that the input parameter will be of the correct, int32 parsable type, and will attempt to resolve the parameter itself before it executes its Select Command! This is not what I want; I want my code to validate the input and cast the parameter to an appropriate value. So I needed simply to go into the page’s source code and modify the parameter declarations from this:
<asp:QueryStringParameter Name=”ID” QueryStringField=”ID” Type=”Int32″ />
<asp:QueryStringParameter Name=”ID” QueryStringField=”ID” />
I made the changes, saved, and success! The page successfuly executed the OnSelecting code, invalidating my bad input and forcing the value to zero, showing me (and more importantly, the general public) a much more helpful message.
Remember when handling the OnSelecting event for parameter validation to ensure that the input parameters are not explicitly cast in the source view, but instead are handled by your own validation code. Til next time, happy coding!