Back

TechnologyJul 01, 2013

ASP.NET Control Validation On-The-Fly

Kevin King

On a recent project we were met with an interesting conundrum: My development team needed to create a functional, yet temporary user interface for a client to test while our User Experience team designed the real thing. We needed to create a quick and easy user experience without user experience experts.

Our (amazing) User Experience team would work through the visual design and flow of the application while my development team would start building in parallel. Because we would not have the luxury of fully approved comps before we built the user interface, we used a popular styling framework called Bootstrap. That gave us a leg up and some easy-to-implement, consistent styles across the various parts of the web application. This was important because our client needed something tactile to use and test before the actual user experience would be implemented. Due to the nature of the application, there were many occasions when we needed to do form validation on fields ranging from textboxes, checkboxes, dropdown lists, date-pickers, etc. In addition to that, many of the validations were more complex than just “date must be valid,” or “must check this box,” or “value must be numeric.”

So we put our thinking caps on and took a moment to come up with a way to implement generic form validation with as light a footprint as possible. After all, we would be pleasantly schooled on the ways of proper user experience design in the near future.

To summarize, our main goals were:

  1. Provide the user with a functional application with appropriate form level validation with messaging

  2. Perform complex validation operations

  3. Spend as little time as possible on this effort

  4. Leave as little of a footprint on our presentation layer as possible

Considering the Options Our first thought was to just use the built-in ASP.NET validation controls. This thought faded quickly due to goals #2 and #4. While ASP.NET provides ways to do custom validation on the server, we didn’t want to jump through those hoops all over the place with events and unnecessarily heavy code. Also those controls would have left intricate spider webs of ASP markup that would need careful grooming when we removed it later.

Our next thought was to just have a hidden error label at the top of each screen that became visible when errors occurred. This seemed much simpler than the first idea, but we quickly realized that this was too limited for our user’s needs. They wanted to have the errors show up next to the offending controls. Further, it would have created a smaller footprint, but still a footprint all the same.   The Solution Over coffee and a delicious granola bar (that may or may not have been used together in a dipping arrangement), my colleague and I came to the same realization simultaneously. Why don’t we just create a custom class that injected a styled error message next to our offending control? We could satisfy the first goal because we know where the message will go, and the user will be able to easily understand what is incorrect or missing. Also we would have complete control over the validation in our server side code. If we were able to create this class and make it re-usable, it wouldn’t take much time to drop it in wherever we wanted. And last but not least, we wouldn’t be touching the markup in any way, making the cutover simple and quick.

Here is the code for our new class:

public class ControlValidations {         private const string CssClass = "ControlError";     public static void CustomValidationControl(Control controlToValidate, string errorMessage, bool highlight = true)         {             Control parentControl = controlToValidate.Parent; var errorMessageContainer = new HtmlGenericControl("span");          errorMessageContainer .Attributes.Add("class", CssClass);            errorMessageContainer .InnerText = errorMessage;             parentControl.Controls.AddAt(parentControl.Controls.IndexOf(controlToValidate) + 1, errorMessageContainer );             if (highlight)                 ((WebControl)controlToValidate).BackColor = Color.LightYellow;       }     } 

You’ll notice that it’s not very much code – this is intentional. You’ll also probably notice that there is a CSS class property that we’re using. While we may not be graphic designers and user experience experts – by golly we can write some CSS to make a label red and give it a nice container with good color contrasts. Depending on your taste, you can create any CSS class you want. As long as it’s on the page where you use this code, you’re good to go. We are using site skins, so we just threw it in there temporarily.

How does it work?

  • The control being validated, an error message, and an optional Boolean for highlighting are passed into the method CustomValidationControl

  • First the parent is determined

  • Next we create a new span element to be our error message container

  • Then we add our fancy CSS class to the span and set the InnerText attribute to our error message

  • After that we actually inject the span into the parent of our control one index position over, meaning that it will always show up to the right of our control

  • And finally we optionally highlight the back color of the control to a nice, soft yellow

Here is what it looks like in action:

Future Options Because one of our goals was to not spend too much time on this, I purposefully did not make further modifications for the sake of this blog.  I will leave you with a few ideas I have to make this even more functional, extensible, and re-usable.

  • Allow for non ASP.NET controls to be passed in, like <input /> or <textarea />

  • Pass the validation function into the method as an Action or Func to make it easier to use

  • Convert the class to JavaScript

It is simple, clean… elegant. Have suggestions on how to make the code better?  Or have an alternate idea to achieve the stated objectives?  We would love to hear your feedback through the comment section below or by tweeting us at @CrederaMSFT.

Enjoy.