Creating a Custom Validation Control in ASP.NET
The BaseValidator class defines the basic implementation needed for all Validation controls. There are 6 Validation Controls included in the ASP.NET 2.0 and ASP.NET 3.5 framework which validate controls to prevent the users from entering wrong data. However, there are a few shortcomings in these controls. The good part is that ASP.NET provides the framework to create new validation controls. If you would like to create your own validation control, you can do so by deriving a new control from the BaseValidator abstract class. In this article, we will explore how to create a custom validation control in ASP.NET and provide both Server and Client Side Validation for the same.
Step 1: Create an ASP.NET Website (File > New > Website). Drag and drop a CheckBoxList, RadioButtonList and a Button control on to the page.
Step 2: Let us first complete the task of populating the CheckBoxList and RadioButtonList controls in the Page_Load event as shown below:
C#
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
List<string> lstStr = new List<string>();
lstStr.Add("Item 1");
lstStr.Add("Item 2");
lstStr.Add("Item 3");
lstStr.Add("Item 4");
CheckBoxList1.DataSource = lstStr;
CheckBoxList1.DataBind();
RadioButtonList1.DataSource = lstStr;
RadioButtonList1.DataBind();
}
}
VB.NET
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If (Not Page.IsPostBack) Then
Dim lstStr As List(Of String) = New List(Of String)()
lstStr.Add("Item 1")
lstStr.Add("Item 2")
lstStr.Add("Item 3")
lstStr.Add("Item 4")
CheckBoxList1.DataSource = lstStr
CheckBoxList1.DataBind()
RadioButtonList1.DataSource = lstStr
RadioButtonList1.DataBind()
End If
End Sub
Step 3: Our next step would be to create the custom validation control. But before that, let us quickly take an overview of what we are trying to achieve. This sample will demonstrate that the user should select at least one checkbox and one radiobutton before submitting the form to the server. For this purpose, we will first show how to create a custom validation control to perform server-side validation and then extend the control to support client-side validation too.
Note: If you are wondering why we have chosen to create a custom validation control instead of using a CustomValidator, then I would state that the main reason for doing so is ‘reusability’. You would soon see that we will be using the same custom validation control to validate both the CheckBoxList as well as RadioButtonList. It is as simple as registering the assembly and start using it.
Step 4: To create our custom validation control, Right click the project > Add New Item > From the Template, choose ‘Class’ > Rename the class to ‘ListValidator’ or anything you like > Choose the Language (C# or VB) > Click on Add.
Note: Visual Studio would prompt you to add the class to the App_Code. Choose yes to do so.
Step 5: As already discussed, we will be deriving from the BaseValidator abstract class. You will need to implement the ‘EvaluateIsValid’ method which returns a Boolean value indicating if the field/control being validated is valid or not. The code for the server side validation will be similar to the following:
Server-Side Validation
C#
namespace CustomListValidator
{
///<summary>
/// Summary description for ListValidator
///</summary>
public class ListValidator : BaseValidator
{
public ListValidator()
{
}
protected override bool ControlPropertiesValid()
{
Control ctrl = FindControl(ControlToValidate) as ListControl;
return (ctrl != null);
}
protected override bool EvaluateIsValid()
{
return this.CheckIfItemIsChecked();
}
protected bool CheckIfItemIsChecked()
{
ListControl listItemValidate = ((ListControl)this.FindControl(this.ControlToValidate));
foreach (ListItem listItem in listItemValidate.Items)
{
if (listItem.Selected == true)
return true;
}
return false;
}
}
}
VB.NET
Namespace CustomListValidator
''' <summary>
''' Summary description for ListValidator
''' </summary>
Public Class ListValidator
Inherits BaseValidator
Public Sub New()
End Sub
Protected Overrides Function ControlPropertiesValid() As Boolean
Dim ctrl As Control = TryCast(FindControl(ControlToValidate), ListControl)
Return (Not ctrl Is Nothing)
End Function
Protected Overrides Function EvaluateIsValid() As Boolean
Return Me.CheckIfItemIsChecked()
End Function
Protected Function CheckIfItemIsChecked() As Boolean
Dim listItemValidate As ListControl = (CType(Me.FindControl(Me.ControlToValidate), ListControl))
For Each listItem As ListItem In listItemValidate.Items
If listItem.Selected = True Then
Return True
End If
Next listItem
Return False
End Function
End Class
End Namespace
In the code snippet shown above, we override the EvaluateIsValid() method. The ‘ControlToValidate’ is cast to a ListControl, which is an abstract base class for all list-type controls. We then loop through all the ListItems and if one of the items in both the CheckBoxList as well as RadioButtonList is checked by the user, we return true, else we return false.
In order to use this custom validation control on the CheckBoxList and RadioButtonList kept in our page, we will use the <%@ Register %> directive as shown below:
<%@ Register TagPrefix="CLV" Namespace="CustomListValidator" %>
<div>
<asp:CheckBoxList ID="CheckBoxList1" runat="server">
</asp:CheckBoxList></div>
<CLV:ListValidator runat="server" ID="custLstVal" ControlToValidate="CheckBoxList1" ErrorMessage="At least one item in the checkboxlist should be checked" />
<asp:RadioButtonList ID="RadioButtonList1" runat="server">
</asp:RadioButtonList>
<CLV:ListValidator runat="server" ID="custRadVal" ControlToValidate="RadioButtonList1" ErrorMessage="At least one item in the radiobuttonlist should be checked" />
<br />
<br />
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" />
As you will observe, the two controls are being validated by the same custom validation control that we are building. Run the application and click on the button without checking any items in the two controls. Two error messages are displayed when the form is submitted.
Step 6: We saw how to perform server side validation. Let us see how we can now perform validation directly on the client side, without a postback. To perform client side validation, you would need to override OnPreRender and create the javascript function using a StringBuilder object and output it using Page.ClientScript.RegisterClientScriptBlock().
Client-Side Validation
The code with the OnPreRender and JavaScript function will look similar to the following. This code is to be added in the same class where the server-side validation code was added.
C#
protected override void OnPreRender(EventArgs e)
{
// Determines whether the validation control can be rendered
// for a newer ("uplevel") browser.
// check if client-side validation is enabled.
if (this.DetermineRenderUplevel() && this.EnableClientScript)
{
Page.ClientScript.RegisterExpandoAttribute(this.ClientID, "evaluationfunction", "CheckIfListChecked");
this.CreateJavaScript();
}
base.OnPreRender(e);
}
protected void CreateJavaScript()
{
StringBuilder sb = new StringBuilder();
sb.Append(@"<script type=""text/javascript"">function CheckIfListChecked(ctrl){");
sb.Append(@"var chkBoxList = document.getElementById(document.getElementById(ctrl.id).controltovalidate);");
sb.Append(@"var chkBoxCount= chkBoxList.getElementsByTagName(""input"");");
sb.Append(@"for(var i=0;i<chkBoxCount.length;i++){");
sb.Append(@"if(chkBoxCount.item(i).checked){");
sb.Append(@"return true; }");
sb.Append(@"}return false; ");
sb.Append(@"}</script>");
Page.ClientScript.RegisterClientScriptBlock(GetType(),"JSScript", sb.ToString());
}
VB.NET
Protected Overrides Sub OnPreRender(ByVal e As EventArgs)
' Determines whether the validation control can be rendered
' for a newer ("uplevel") browser.
' check if client-side validation is enabled.
If Me.DetermineRenderUplevel() AndAlso Me.EnableClientScript Then
Page.ClientScript.RegisterExpandoAttribute(Me.ClientID, "evaluationfunction", "CheckIfListChecked")
Me.CreateJavaScript()
End If
MyBase.OnPreRender(e)
End Sub
Protected Sub CreateJavaScript()
Dim sb As StringBuilder = New StringBuilder()
sb.Append("<script type=""text/javascript"">function CheckIfListChecked(ctrl){")
sb.Append("var chkBoxList = document.getElementById(document.getElementById(ctrl.id).controltovalidate);")
sb.Append("var chkBoxCount= chkBoxList.getElementsByTagName(""input"");")
sb.Append("for(var i=0;i<chkBoxCount.length;i++){")
sb.Append("if(chkBoxCount.item(i).checked){")
sb.Append("return true; }")
sb.Append("}return false; ")
sb.Append("}</script>")
Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "JSScript", sb.ToString())
End Sub
As you observe, we override the OnPreRender method and use the RegisterExpandoAttribute to assign the function name ‘CheckIfListChecked’ an attribute called ‘evaluationfunction’. The javascript function(CheckIfListChecked) takes one parameter, the validator object and returns ‘true’ if Valid (item in both Radiobuttonlist or CheckBoxList is checked) and ‘false’ if Invalid (Item in either Radiobuttonlist or CheckBoxList is not selected).
Note: If you observe, there is a call to the base.OnPreRender() in the OnPreRender method. This is done to make sure that if the users have turned off javascript on their browsers, then this call passes the control back to the page and allows the rendering to continue by calling base.OnPreRender() .
The javascript function is created using a StringBuilder object and is output using Page.ClientScript.RegisterClientScriptBlock()
When the page is run, the javascript output to the browser will look similar to the following:
<script type="text/javascript">
function CheckIfListChecked(ctrl)
{
var chkBoxList = document.getElementById(document.getElementById(ctrl.id).controltovalidate);
var chkBoxCount= chkBoxList.getElementsByTagName("input");
for(var i=0;i<chkBoxCount.length;i++)
{
if(chkBoxCount.item(i).checked)
{
return true;
}
}return false;
}
</script>
Step 7: The last step would be to add the EnableClientScript="true" to our custom validation controls as shown below:
<CLV:ListValidator runat="server" ID="custLstVal" EnableClientScript="true" ControlToValidate="CheckBoxList1" ErrorMessage="At least one item in the checkboxlist should be checked" />
<CLV:ListValidator runat="server" ID="custRadVal" EnableClientScript="true" ControlToValidate="RadioButtonList1" ErrorMessage="At least one item in the radiobuttonlist should be checked" />
That’s pretty much it. This time when you run the application, the custom validation control handles both server-side as well as client-side validation. If JavaScript is enabled on your browsers, the validation errors are displayed before the form is posted back to the server. The entire source code of the application can be downloaded from here. I hope you liked the article and I thank you for viewing it.
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of
DotNetCurry,
DNC Magazine for Developers,
SQLServerCurry and
DevCurry. He has also authored a couple of books
51 Recipes using jQuery with ASP.NET Controls and
The Absolutely Awesome jQuery CookBook.
Suprotim has received the prestigious Microsoft MVP award for Sixteen consecutive years. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that offers Digital Marketing and Branding services to businesses, both in a start-up and enterprise environment.
Get in touch with him on Twitter @suprotimagarwal or at LinkedIn