Deborah's Developer MindScape






         Tips and Techniques for Web and .NET developers.

July 16, 2009

Validation Class

Filed under: C#,OOP,VB.NET @ 6:15 pm

A common requirement in most applications is to validate the data entered by the user. This is such a common requirement, that it makes sense to build a reusable Validation class. This post details the beginnings of a .NET Validation class.

The class was originally designed to validate business object properties. But it could also be used to directly validate fields in your user interface if you are not yet using business objects.

In C#:

using System;
using System.Collections.Generic;
using System.Text;

namespace InStepLibrary
{
    public class Validation
    {

    }
}

In VB:

Imports System.Text

Public Class Validation

End Class

This class uses a StringBuilder, hence the need for the System.Text imports.

The Validation class has three properties.

In C#:

public int Count
{
    get
    {
        return ValidationList.Count;
    }
}

public string this[string propertyName]
{
    get
    {
        if (ValidationList.ContainsKey(propertyName))
            return ValidationList[propertyName];
        else
            return null;
    }
}

private Dictionary<String, String> ValidationList { get; set; }

In VB:

Public ReadOnly Property Count() As Integer
    Get
        Return ValidationList.Count
    End Get
End Property

Public ReadOnly Property Item(ByVal propertyName As String) As String
    Get
        If ValidationList.ContainsKey(propertyName) Then
            Return ValidationList.Item(propertyName)
        Else
            Return Nothing
        End If
    End Get
End Property

Private _ValidationList As Dictionary(Of String, String)
Private Property ValidationList() As Dictionary(Of String, String)
       Get
        Return _ValidationList
    End Get
    Set(ByVal value As Dictionary(Of String, String))
        _ValidationList = value
    End Set
End Property

The ValidationList property retains a private Dictionary of validation errors. The key of the dictionary is the property name and the value is the error text. For example, the “LastName” property may have a validation error such as “Last Name is required.”

The Count property returns the number of properties with validation errors by returning the count of the ValidationList items.

The Item property provides access to the validation errors given a property name. This property is implemented as the class indexer in C#.

The constructor ensures that a new instance of the ValidationList Dictionary is created.

In C#:

public Validation()
{
    // Create the list to contain the validation errors
    ValidationList = new Dictionary<String, String>();
}

In VB:

Public Sub New()
    ‘ Create the list to contain the validation errors
    ValidationList = New Dictionary(Of String, String)
End Sub

The ToString method is overwritten in the Validation class to build a single string containing all of the validation errors.

In C#:

public override string ToString()
{
    StringBuilder sb = new StringBuilder();

    foreach (string k in ValidationList.Keys)
        sb.AppendLine(k + ": " + ValidationList[k]);

    return sb.ToString();
}

In VB:

Public Overrides Function ToString() As String
    Dim sb As New StringBuilder

    For Each k As String In ValidationList.Keys
        sb.AppendLine(k & ": " & ValidationList(k))
    Next
    Return sb.ToString
End Function

This method uses the StringBuilder class to build up the potentially large string of errors.

When a validation error is added to the list, it is added for a particular property. If the property already has a validation error, additional validation errors are appended to it, separated by semi-colons (;). An AddValidationError method handles this logic.

In C#:

private void AddValidationError(string propertyName, string message)
{
    // If the property already has a message, append this message
    if (ValidationList.ContainsKey(propertyName))
    {
        string existingMessage = ValidationList[propertyName];

        if (!existingMessage.Contains(message))
            // Append the new message to the existing message
            ValidationList[propertyName] += "; " + message;
    }
    else
        // Add the message to the validation list
        ValidationList.Add(propertyName, message);
}

In VB:

Private Sub AddValidationError(ByVal propertyName As String, _
         ByVal message As String)

    ‘ If the property already has a message, append this message
    If ValidationList.ContainsKey(propertyName) Then
        Dim existingMessage As String = ValidationList(propertyName)

        If Not existingMessage.Contains(message) Then
            ‘ Append the new message to the existing message
            ValidationList(propertyName) &= "; " & message
        End If
    Else
        ‘ Add the message to the validation list
        ValidationList.Add(propertyName, message)
    End If
End Sub

A ValidateClear method clears any existing validation errors for a property. This method should be called before performing any new validation on the property. For example, the user leaves the Last Name field empty. The validation is performed and a validation error entry is created in the ValidationList. Then the user enters a value into the last name field. The original validation error must be cleared before revalidating the value.

In C#:

public void ValidateClear(string propertyName)
{
    // If the Property doesn’t have any messages, this is done
    if (ValidationList.ContainsKey(propertyName))
        // Otherwise, remove the entry
        ValidationList.Remove(propertyName);
}

In VB:

Public Sub ValidateClear(ByVal propertyName As String)
    ‘ If the Property doesn’t have any messages, this is done
    If ValidationList.ContainsKey(propertyName) Then
        ‘ Otherwise, remove the entry
        ValidationList.Remove(propertyName)
    End If
End Sub

The ValidateClear method uses the Remove method of the Dictionary to remove any Dictionary entry for the property.

That’s it for the basics of the Validation class. The only thing that is left to do is build all of the methods to perform the types of validation that your application requires.

For example, a common requirement is to ensure that a property is not left blank.

In C#:

public bool ValidateRequired(string propertyName,
                             string value)
{
    string newMessage = String.Empty;

    if (String.IsNullOrEmpty(value))
    {
        newMessage =
           String.Format("{0} is required, please enter a valid value",
                                    propertyName);
        // Add the message to the validation list
        AddValidationError(propertyName, newMessage);
        return false;
    }
    else
        return true;
}

In VB:

Public Function ValidateRequired(ByVal propertyName As String, _
                                 ByVal value As String) As Boolean
    Dim newMessage As String = String.Empty

    If String.IsNullOrEmpty(value) Then
      newMessage = _
        String.Format("{0} is required. Please enter a valid value.", _
                                  propertyName)
      ‘ Add the message to the validation list
      AddValidationError(propertyName, validationMessage)
      Return False
    Else
      Return True
    End If

End Function

This function performs the validation, adding a validation error as appropriate.

Another common requirement is that a property not exceed a maximum length.

In C#:

public Boolean ValidateLength(string propertyName,
                                string value, int maxLength)
{
    String newMessage = String.Empty;

    if (!String.IsNullOrEmpty(value) && value.Length > maxLength)
    {
        newMessage = String.Format("{0} has a maximum size of {1}",
                                 propertyName, maxLength);
        // Add the message to the validation list
        AddValidationError(propertyName, newMessage);
        return false;
    }
    else
        return true;
}

In VB:

Public Function ValidateLength(ByVal propertyName As String, _
         ByVal value As String, ByVal maxLength As Integer) As Boolean
    Dim sMessage As String = String.Empty

    If Not String.IsNullOrEmpty(value) AndAlso _
                             value.Length > maxLength Then
        sMessage = String.Format("{0} has a maximum size of {1}.", _
                                propertyName, maxLength)
        ‘ Add the message to the validation list
        AddValidationError(propertyName, sMessage)
        Return False
    Else
        Return True
    End If
End Function

You get the idea. You can add any number of these to perform whatever validation your application requires.

Some additional suggestions:

  • ValidateAlphaNumeric
  • ValidateDirectory
  • ValidateEnum
  • ValidateFileExists
  • ValidateMinLength
  • ValidateNonZero
  • ValidateNoSpaces
  • ValidateNumeric

You can create any validation method you need for your application. Just add code to perform the validation and then call AddValidationError as appropriate.

You call these validation methods from your business objects as shown below.

NOTE: This code assume you have a ValidationInstance variable that is declared in your class as a new instance of the Validation class.

In C#:

private string _LastName;
public string LastName
{
    get { return _LastName; }
    set
    {
        if (_LastName == null || _LastName != value)
        {
            string propertyName = "LastName";
            _LastName = value;

            // Validate the last name
            ValidationInstance.ValidateClear(propertyName);
            ValidationInstance.ValidateRequired(propertyName, value); 
        }
    }
}

In VB:

Private _LastName As String
Public Property LastName() As String
    Get
        Return _LastName
    End Get
    Set(ByVal value As String)
        If _LastName Is Nothing OrElse _LastName <> value Then
            Dim propertyName As String = "LastName"
            _LastName = value

            ‘ Validate the last name
            ValidationInstance.ValidateClear(propertyName)
            ValidationInstance.ValidateRequired(propertyName, value) 
        End If
    End Set
End Property

Or you can call these validation methods directly from your user interface as shown below.

NOTE: This code assume you have a ValidationInstance variable that is declared in your form as a new instance of the Validation class.

In C#:

private void textBox1_Validating(object sender, CancelEventArgs e)
{
    string propertyName  = "Last Name";
    validationInstance.ValidateClear(propertyName);
    validationInstance.ValidateRequired(propertyName, textBox1.Text);
    validationInstance.ValidateLength(propertyName, textBox1.Text, 20);

    if (validationInstance.Count > 0)
        errorProvider1.SetError(textBox1,
                        validationInstance[propertyName]);
    else
        // Clear the validation error
        errorProvider1.SetError(textBox1, String.Empty);
}

In VB:

Private Sub TextBox1_Validating(ByVal sender As Object, _
             ByVal e As System.ComponentModel.CancelEventArgs) _
             Handles TextBox1.Validating
    Dim propertyName As String = "Last Name"
    validationInstance.ValidateClear(propertyName)
    validationInstance.ValidateRequired(propertyName, TextBox1.Text)
    validationInstance.ValidateLength(propertyName, TextBox1.Text, 20)

    If validationInstance.Count > 0 Then
        ErrorProvider1.SetError(TextBox1, _
                        validationInstance.Item(propertyName))
    Else
        ‘ Clear the validation error
        ErrorProvider1.SetError(TextBox1, String.Empty)
    End If
End Sub

Hope this helps you encapsulate all of your validation logic into a reusable class.

Enjoy!

9 Comments

  1.   Orson — August 8, 2009 @ 3:45 am    Reply

    I love it. I one great post.

    Thanks

  2.   Joseph Homshaw — September 6, 2009 @ 7:40 pm    Reply

    What a great class, thank you very much!!

  3.   Vinz — January 6, 2010 @ 4:07 am    Reply

    It’s a very nice class but i how can i force the validation of an object ?

    Example : i have an object whith a property “ID” with a ValidateRequired rules set.
    If i just make a new object, the “ID” property is null but the broken rule is not set because i don’t call the set method of the property.
    How can i force the validation of all the rules of the object (a sort of validate() method of the object) ?
    Thx

  4.   tjuni — June 5, 2012 @ 9:01 pm    Reply

    Thank you so much for providing this code. I use it and your ObjectBase and ListBase code as the basis of all of my classes that require adding/editing/deleting via a user interface.

  5.   DeborahK — August 26, 2012 @ 7:31 pm    Reply

    Vinz –
    There are several ways to force validation. One way is to use a Create method on your business object that always sets the properties, even if it just sets them to 0/null. That will ensure the setters are called.

    Another technique is to create a Validate method that manually checks your required fields if, for example, the user presses Save without entering any data.

    Hope this helps.

  6.   Luiz Estevo — November 15, 2012 @ 11:24 pm    Reply

    I just want to say “Thank You” for sharing such a beautiful, clean and usefull class. It fit into one of my projects just like a glove. Thanks again and keep up the good work!

    Cheers,
    Luiz

  7.   Luiz Estevo — November 16, 2012 @ 12:13 am    Reply

    I just want to say “Thank You” for sharing such a beautiful, clean and usefull class. It fit into one of my projects just like a glove. Thanks again and keep up the good work!

    Cheers,
    Luiz

  8.   Anand Arora — March 5, 2016 @ 3:35 am    Reply

    Awesome post, please correct the ToString function -> ValidationList.Values to ValidationList.Keys (I think it is correct in the VB version) 🙂

    •   deborahk — April 14, 2016 @ 11:13 am    Reply

      Done! Thanks Anand!

RSS feed for comments on this post. TrackBack URI

Leave a comment

© 2016 Deborah's Developer MindScape   Provided by WPMU DEV -The WordPress Experts   Hosted by Microsoft MVPs