Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Validating primitive types with Extension Methods

0.00/5 (No votes)
10 Jul 2012 1  
Using Extension Methods to validate string, integer, datetime, and bool values.

Introduction

Using extension methods can be useful to validate data when you are dealing with untrusted input from various sources (like user entered data on a web page or importing CSV files from an external FTP source).

The download code

The BasicValidator.zip file contains a single static class, with a number of static boolean methods. Each method is an extension of a primitive data type that adds a Validate method to it.

The code requires dotnet 3.5 or higher as it uses optional parameters, named parameters and extension methods (which were only introduced in 3.5).

The BasicValidator class is written in c#, but can be fairly easily translated to VB.Net. Let me google that for you.

Background

I recently found myself in a position where I needed to do a bunch of server side validation for our corporate website. I also knew that the very next project in line was a task engine to process externally generated pdf files and place them into our records management system. In this case, all of the needed meta data would be embedded in the file name of each file.

In order to minimise the amount of validation code for these projects, I came up with an extension method class to handle the most simple cases. All of the data types I would be dealing with would be integers, strings, dates or bools, so my library only deals with these types. It should be fairly trivial to add other types when they are needed.

One other desired outcome was readability. When I look at this code in two years time, I want to be able to easily identify what my validation rules are without having to trace through code or even refer back to the validation library.

Using the code

There are six methods in the validation class. One for each of:

  • Nullable int
  • Int
  • String
  • Nullable datetime
  • Datetime
  • Nullable bool

Note: Nullable bool and nullable int are there due to a quirk with out CRM system, where all data types are nullable, but often our business rules require an actual value

Each method makes use of named parameters with default values, so using any of the methods is fairly trivial

Nullable Integer

Available Rules:

  • bool CanBeNull = true
  • int MinVal = int.MinValue
  • int MaxVal = int.MaxValue

Example:

int? untrustedData = 42
if(! untrustedData.Validate(CanBeNull:false, MaxVal:40){
   return "Sorry, data out of range";
}

Integer

Avaliable Rules:

  • int MinVal = int.MinValue
  • int MaxVal = int.MaxValue

Example:

int untrustedData = 42
if(! untrustedData.Validate(MinVal:50){
   return String.Format("Sorry, {0} is not a valid number. Min value is 50", untrustedData);
}

string

Available Rules:

  • string regEx = null
  • bool CanBeNull = true
  • bool CanBeEmpty = true
  • int MaxLength = int.MaxValue
  • string MustStartWith = null
  • string MustContain = null
  • string MustEndWith = null
  • bool MustBeAnInt = false
  • bool MustBeAnAusDate = false
  • bool MustBeAnEmailAddress = false

Notes: The CanBeNull and CanBeEmpty rules are processed first. If they are left at their default value (true) and the string is null or empty, the validator will return true regardless of any other rules. This behaviour is by design. If you want to check that a string has a minimum length, and/or matches a regEx and/or any other rule AND is not null or empty, make sure you set both CanBeNull and CanBeEmpty to false. Without these settings, what you are checking for is "does this string match my rule(s) OR is it null Or is it an empty string".

The regEx rule takes a regular expression and returns true if the string value matches the regEx. It is up to you to make sure your regEx works.

The MustBeAnAusDate attempts to match a "dd/mm/yyyy" date patern. Feel free to add a US (or any other culture) date test.

The MustBeAnEmailAddress uses a regEx pattern of "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$" to attempt to verify that the string is a valid email address. Again, feel free to change this to whatever regEx takes your fancy.

Example:

var untrustedData = "Some.Email@Address"
if(!untrustedData.Validate(CanBeNull:false, MustBeAnEmailAddress:true){
    return string.Format("{0} is not a valid email address", untrustedData);
}
 
if(!untrustedData.Validate(MaxLength:10){
    return string.Format("{0} is too long, maximum length is 10 characters", untrustedData);
}

Nullable DateTime

Available Rules:

  • DateTime? MinDate = null
  • DateTime? MaxDate = null
  • bool CanBeNull = true

Example:

var untrustedData = DateTime.Now;
var yesterday = DateTime.Now.AddDays(-1);
if(!untrustedData.Validate(MaxDate:yesterday){
    return string.Format("{0} is not a valid date, must be before {1}", untrustedData, yesterday);
}

DateTime

Available Rules:

  • DateTime? MinDate = null
  • DateTime? MaxDate = null

Example:

var untrustedData = DateTime.Now;
var tomorrow = DateTime.Now.AddDays(1);
if(!untrustedData.Validate(MinDate:tomorrow){
    return string.Format("{0} is not a valid date, must be after {1}", untrustedData, tomorrow);
}

Nullable Boolean

Available rule:

  • bool CanBeNull = true

Example:

bool? untrustedData = null;
if(!untrustedData.Validate(CanBeNull:false){
    return "Null values are not allowed";
}

Points of Interest

It is posible to use these validation methods without the named parameters if you explicity pass in parameter values up to the rule you are actually interested in. I don't advise this approach as it will make your code much harder to read and maintain.

I had not played with extension methods much before writing this validation class and so was quite pleased with the power it gave me. I was able to simplify and mimimise the validation sections of my code so that I was just dealing with simple rules rather than writing extensive methods.

My approach here is to just return boolean values on each type, but there is no reason not to refractor this to include an out or ref parameter to include user feedback messages when validation fails (if that is something you need).

History

Version 1: 2012-07-10

Uploaded a new version of BasicValidator.cs that has a number of minor improvements. Usage and Method signatures are unchanged: 2012-07-11

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here