Extending validation of ASP.NET web forms
I normally use jQuery validation any chance I get when it comes to validation, but sometimes you find yourself in situations where this isn’t the best option. jQuery validation normally doesn’t play very nice with ASP.NET web forms and it’s not unusual to have to make all kinds of adaptions for custom validation scenarios (in ASP.NET MVC it works much better).
I was recently asked to make several updates to an existing ASP.NET web forms application that included several forms of varying complexity. They all relied heavily on ASP.NET validation controls. One feature that was requested was to have validation as the user types and not on blur, another was to have icons signaling whether an input field had been successfully validated or not. Both notoriously difficult to implement using the traditional validation controls of ASP.NET web forms.
This brings us to a choice. Do we remove the validation controls and rewrite the validation using jQuery validation and custom server side validation? Do we keep the validation controls and try to customize them to accommodate the new client requests?
In this particular case I really didn’t want to have to rewrite all the validation and customizing the validation controls didn’t sound like a whole lot of fun either, so I tried to find some kind of a middle way. I came up with some sort of mysterious ASP.NET web controls and client side jQuery validation hybrid that look like this:
//Create some sort of entry object. validation is as good a name as any
var validation = {
init: function () {
var elems = $('body').find('[data-validation]');
elems.each(function (index, elem) {
$(elem).on('blur keyup change', function () {
validation.validateElement($(this));
});
});
},
validateElement: function (elem) {
var validationRules = $(elem).attr('data-validation').split(' ');
var valid = false;
for (var i = 0; i < validationRules.length; i++) {
var func = validation.rules[validationRules[i]];
valid = func($(elem).val());
if (!valid)
break;
}
var after = $(elem).next();
if (after.hasClass('validationResult')) {
after.remove();
}
if (valid) {
//Do whatever you want to happen when an element is valid
$(elem).after('<span class="validationResult success"><img class="validation-img" src="/Templates/Static/Images/check.png"/></span>');
} else {
//Do whatever you want to happen when an element is invalid
$(elem).after('<span class="validationResult fail"><img class="validation-img" src="/Templates/Static/Images/cross.png"/></span>');
}
},
rules: {
required: function (val) {
return val != undefined && val.trim() != '';
},
personalNumber: function (val) {
//we allow null or empty values
if (val == '' || val == undefined)
return true;
var persRegex = /^\d{6}-\d{4}$/;
return persRegex.test(val);
},
email: function (val) {
//we allow null or empty values
if (val == '' || val == undefined)
return true;
var emailRegex = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return emailRegex.test(val);
},
phone: function (val) {
//we allow null or empty values
if (val == '' || val == undefined)
return true;
var phoneRegex = /^(\+|[0])\d[0-9- ]{5,}$/;
return phoneRegex.test(val);
},
number: function (val) {
if (val == '' || val == undefined)
return true;
var numberRegex = /^\d{1,}$/;
return numberRegex.test(val);
}
}
}
Nothing complicated. We simply hook up our validation to any elements with the data-validation attribute. Then we create a generic validation method that looks at the values of the attribute and calls the appropriate validation method.
Simple and extendable. Without the actual rules it’s just shy of 30 lines of javascript.
This way I could leave my ASP.NET validation controls as they were and hook this up to the existing textboxes something like this:
<asp:TextBox id="tb1" data-validation="required number" runat="server" />
And that’s it. Although bear in mind that I have attached no logic to the submit button at this point (in my case it wasn’t necessary).