Introduction
We all need to write secure applications, and the first pillar of a secure application is the validation of all user inputs. Hopefully ASP.NET was designed with that in mind. A lot of validations take place by default without any effort by the developer. In the tool box, ASP.NET offers Validation Server Controls that the developer can use to validate user inputs.
Unfortunately, each instance of a validation control is associated with only one control. There is no built in mechanism that allows us to use the same validator to validate multiple controls. Even though many controls in the same page share the same validation rules, the developer still creates the same validators for each control.
ValidationTemplate
is a server control that allows the use of the same validators to validate multiple controls.
Using the Code
The library contains two controls ValidationTemplate
and Validator
.
ValidationTemplate
is the main server control. You use it to define the validation rules by using one or more validation server controls, and also to specify the list of the controls to validate.
<cc1:ValidationTemplate ID="ValidationTemplate1" runat="server"
DefaultValidationGroup="InsertObject">
<Validators>
<asp:RequiredFieldValidator runat="server"
ErrorMessage="{0} is mandatory">*
</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator runat="server"
ErrorMessage="{0} is incorrect" ValidationExpression=
"\d+">*</asp:RegularExpressionValidator>
<asp:RangeValidator runat="server" ErrorMessage="{0}
should be between 10 and 100"
MaximumValue="100" MinimumValue="10" Type="Integer">*
</asp:RangeValidator>
</Validators>
<ControlsToValidate>
<cc1:ControlDesc CID="txtHeight" Label="Height" />
<cc1:ControlDesc CID="txtWidth" Label="Width" />
<cc1:ControlDesc CID="txtDepth" Label="Depth" />
</ControlsToValidate>
</cc1:ValidationTemplate>
ValidationTemplate
contains the following attributes:
Validators
: which is an ITemplate
. Use it to define the validation logic by dropping one or more validation server controls. The Text
and the ErrorMessage
properties of the validation controls can contain a place holder {0}
to print a custom message for each control.ControlsToValidate
: which is a collection of ControlDesc
. Use it to define the list of the control to validate. Each instance of ControlDesc
contains two properties. CID
: is the control id that will be validated. And Label
which is the text that will replace the place holder used in validation server controls. ValidationTemplate
will look for the controls in the current Naming Container only.DefaultValidationGroup
: Use it to define the default validation group of the controls. This validation group will be used if the validator didn't specify a validation group.ForceValidationGroup
: by default it is false
. If you set it to true
, this will force it to override the validation group by the one specified in DefaultValidationGroup
. If you set ForceValidationGroup
to true
and DefaultValidationGroup
to ""
, this will clear all validation groups specified in the validators.
You can use the control in design mode. Use "Edit Templates" from the Tasks Menu to edit the validators template. And the property window to edit the rest of the properties.
At runtime, the ValidationTemplate
will instantiate the validation template and insert an instance after each control to be validated. If you want to control where the validators are instantiated, use the Validator
control. The Validator
control also allows to validate controls that are in other Naming Containers. For example, you can use it to validate the controls in Databound controls such as GridView
.
<cc1:Validator ID="Validator1" runat="server" ControlToValidate="txtHeight"
Label="Height" TemplateId="ValidationTemplate1"
ValidationGroup="UpdateObject" />
The Validator
control contains the following properties:
ControlToValidate
: The control to be validated. You can use it with only one control.Label
: To generate a custom error message. ValidationGroup
: This validation group will always override the one specified in the validation template.TemplateId
: The id of ValidationTemplate
that will be used.
Points of Interest
Under the hood ValidationTemplate
don't reuse validation controls. It just instantiated them for each control that should be validated. The validators are just instantiated and inserted in the controls tree just after the control to be validated.
foreach (ControlDesc ctrlDesc in _controlsToValidate)
{
Control ctrl = NamingContainer.FindControl(ctrlDesc.CID);
int idx = ctrl.Parent.Controls.IndexOf(ctrl);
CtrlsContainer cnt = new CtrlsContainer();
_validators.InstantiateIn(cnt);
PrepareValidators(cnt, ctrlDesc, null);
ctrl.Parent.Controls.AddAt(idx + 1, cnt);
}
You can define the validation template in the master page, and then use it in pages via the Validator
control.
The concept behind the ValidationTemplate
control is that it takes a template, instantiates it and injects it anywhere in the page. You can use the same concept to inject things other than validators.
You can adjust the code so you can create validation templates in cascade. Just add TemplateId
property to ValidationTemplate
and combine the generated controls.
History
- 23rd March, 2009: Initial version
Fascinated by good architectures, well thought classes and clean code. I work as a software developer since 2004.