Click here to Skip to main content
15,881,712 members
Articles / Web Development / ASP.NET

Building an ASP.NET Validator Using Data Annotations

Rate me:
Please Sign up or sign in to vote.
4.67/5 (7 votes)
27 Jul 2010CPOL1 min read 48.4K   28   7
The article describes an implementation of an ASP.NET validator that uses the new System.ComponentModel.DataAnnotations assembly that came in .NET 3.5 SP1.

Introduction

In this article I’m going to describe an implementation of ASP.NET validator that uses the new System.ComponentModel.DataAnnotations assembly that came in .NET 3.5 SP1.

The Validator

In order to create the validator, you need to inherit from the BaseValidator abstract class and implement its EvaluateIsValid method. I’ve created an ASP.NET Server Control project and added a control class that does the exact thing. You need to reference the System.ComponentModel.DataAnnotations assembly in order for it to work. Here is how it’s implemented:

C#
namespace Validators
{
  [ToolboxData("<{0}:DataAnnotationValidator 
    runat="server"></{0}:DataAnnotationValidator>")]
  public class DataAnnotationValidator : BaseValidator
  {
    #region Properties

    /// <summary>
    /// The type of the source to check
    /// </summary>
    public string SourceTypeName { get; set; }

    /// <summary>
    /// The property that is annotated
    /// </summary>
    public string PropertyName { get; set; }

    #endregion

    #region Methods

    protected override bool EvaluateIsValid()
    {
      // get the type that we are going to validate
      Type source = GetValidatedType();

      // get the property to validate
      PropertyInfo property = GetValidatedProperty(source);

      // get the control validation value
      string value = GetControlValidationValue(ControlToValidate);

      foreach (var attribute in property.GetCustomAttributes(
               typeof(ValidationAttribute), true)
                 .OfType<ValidationAttribute>())
      {
        if (!attribute.IsValid(value))
        {
          ErrorMessage = attribute.ErrorMessage;
          return false;
        }
      }
      return true;
    }

    private Type GetValidatedType()
    {
      if (string.IsNullOrEmpty(SourceTypeName))
      {
        throw new InvalidOperationException(
          "Null SourceTypeName can't be validated");
      }
      
      Type validatedType = Type.GetType(SourceTypeName);
      if (validatedType == null)
      {
        throw new InvalidOperationException(
            string.Format("{0}:{1}", 
              "Invalid SourceTypeName", SourceTypeName));
      }

      return validatedType;
    }

    private PropertyInfo GetValidatedProperty(Type source)
    {
      PropertyInfo property = source.GetProperty(PropertyName, 
        BindingFlags.Public | BindingFlags.Instance);

      if (property == null)
      {
        throw new InvalidOperationException(
          string.Format("{0}:{1}", 
            "Validated Property Does Not Exists", PropertyName));
      }
      return property;
    }

    #endregion
  }
}

As you can see, I use two main properties in the validator which help me to get the relevant source type name and the property to validate.

Testing the Validator

In order to test the validator, I have created a Web Application project and put inside of it a simple Person class which uses Data Annotations for validation:

C#
namespace ASPNETDataAnnotation 
{
  public class Person 
  { 
    [Required(ErrorMessage="ID is requiered")] 
    public string ID { get; set; } 

    [StringLength(20, ErrorMessage = "First name is too long!")]
    public string FirstName { get; set; } 

    [StringLength(20, ErrorMessage="Last name is too long!")] 
    public string LastName { get; set; } 

    [RegularExpression(
      @"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+*",    
      ErrorMessage="Must be a valid e-mail address")] 
    public string Email { get; set; } 
  } 
}

Also, I’ve created a web form that uses the validator:

ASP.NET
lt;%@ Page Language="C#" AutoEventWireup="true" 
  CodeBehind="WebForm1.aspx.cs" Inherits="ASPNETDataAnnotation.WebForm1" %>

<%@ Register Assembly="Validators" Namespace="Validators" TagPrefix="cc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <div>
            <asp:Label ID="lblID" Text="ID: " runat="server" />
            <asp:TextBox ID="txtID" runat="server" />
            <cc1:DataAnnotationValidator ID="valID" 
                runat="server" ControlToValidate="txtID"
                PropertyName="ID" 
                SourceTypeName="ASPNETDataAnnotation.Person, ASPNETDataAnnotation" />
        </div>
        <div>
            <asp:Label ID="lblFirstName" Text="First Name: " runat="server" />
            <asp:TextBox ID="txtFirstName" runat="server" />
            <cc1:DataAnnotationValidator ID="valFirstName" 
                runat="server" ControlToValidate="txtFirstName"
                PropertyName="FirstName" 
                SourceTypeName="ASPNETDataAnnotation.Person, ASPNETDataAnnotation" />
        </div>
        <div>
            <asp:Label ID="lblLastName" Text="Last Name: " runat="server" />
            <asp:TextBox ID="txtLastName" runat="server" />
            <cc1:DataAnnotationValidator ID="valLastName" 
                runat="server" ControlToValidate="txtLastName"
                PropertyName="LastName" 
                SourceTypeName="ASPNETDataAnnotation.Person, ASPNETDataAnnotation" />
        </div>
        <div>
            <asp:Label ID="lblEmail" Text="E-Mail: " runat="server" />
            <asp:TextBox ID="txtEmail" runat="server" />
            <cc1:DataAnnotationValidator ID="valEmail" 
                runat="server" ControlToValidate="txtEmail"
                PropertyName="Email" 
                SourceTypeName="ASPNETDataAnnotation.Person, ASPNETDataAnnotation" />
        </div>
        <div>
            <asp:Button ID="btnValidate" Text="Validate" runat="server" />
        </div>
    </div>
    </form>
</body>
</html>

Running the web form and clicking on the button while we have bad data will generate a validation error as expected:

WebForm Validation Results

Summary

In the post, I showed one way to create an ASP.NET data annotation validator. In other frameworks like ASP.NET MVC or WCF RIA Services you have such validators implemented.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead sparXys
Israel Israel
Gil Fink is a web development expert and ASP.Net/IIS Microsoft MVP. He is the founder and owner of sparXys. He is currently consulting for various enterprises and companies, where he helps to develop Web and RIA-based solutions. He conducts lectures and workshops for individuals and enterprises who want to specialize in infrastructure and web development. He is also co-author of several Microsoft Official Courses (MOCs) and training kits, co-author of "Pro Single Page Application Development" book (Apress) and the founder of Front-End.IL Meetup. You can read his publications at his website: http://www.gilfink.net

Comments and Discussions

 
GeneralComparing with enterprise library 5.0 Pin
Mogamboo_Khush_Hua19-Sep-10 21:59
Mogamboo_Khush_Hua19-Sep-10 21:59 
GeneralRe: Comparing with enterprise library 5.0 Pin
Mogamboo_Khush_Hua19-Sep-10 22:02
Mogamboo_Khush_Hua19-Sep-10 22:02 
GeneralRe: Comparing with enterprise library 5.0 Pin
Gil Fink19-Sep-10 22:35
Gil Fink19-Sep-10 22:35 
Hi,
Validation using ent-lib isn't the same like data annotations (even though it seems like they do the same thing).
The purpose of data annotation is to add metadata to properties to indicate simple validation scenarios. Putting the annotations won't add validation to your application and you will have to supply your implementation or the framework that you use (for example MVC framework) will supply built in validation implementation for you.
The Validation Application Block is a framework that was built to give solution to variaty of validation scenarios. It includes the validation implementation itself and also include more features that data annotations can't supply like self validation for complex business validations for example.

I hope it clarify the subject.
NewsASP.NET Data Annotation Validator with Client Side Support Pin
Gil Fink1-Aug-10 19:28
Gil Fink1-Aug-10 19:28 
GeneralRe: ASP.NET Data Annotation Validator with Client Side Support Pin
amanek14-Jan-12 1:16
amanek14-Jan-12 1:16 
GeneralSmall correction Pin
Richard Deeming27-Jul-10 4:53
mveRichard Deeming27-Jul-10 4:53 
GeneralRe: Small correction Pin
Gil Fink27-Jul-10 20:03
Gil Fink27-Jul-10 20:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.