Showing posts with label Validation. Show all posts
Showing posts with label Validation. Show all posts

Sunday, May 04, 2008

Credit Card Validation With LINQ

The credit card mod 10 validation algorithm is quite straightforward. Easy enough for me to have a go at writing with LINQ. This example is written as an extension method validator. Let me know if you can make this even more concise.

public ValidationProperty IsCreditCard()
{
   value.Label(label).IsNumeric().WithLengthRange(13.To(18));

   var numbers = value.Trim().Reverse().Select(c => int.Parse(c.ToString()));

   int oddSum = numbers.AtOddPositions().Sum();
   int doubleEvenSum = numbers.AtEvenPositions().SelectMany(i => new int[] { (i * 2) % 10, (i * 2) / 10 }).Sum();

   if ((oddSum + doubleEvenSum) % 10 != 0)
   {
       throw new ValidationException("{0} is not a valid credit card number".With(label));
   }

   return this;
}

Here are the AtOddPositions and AtEvenPositions extension methods:

public static IEnumerable<T> AtOddPositions<T>(this IEnumerable<T> list)
{
   bool odd = false; // 0th position is even
   foreach (T item in list)
   {
       odd = !odd;
       if (odd)
       {
           yield return item;
       }
   }
}

public static IEnumerable<T> AtEvenPositions<T>(this IEnumerable<T> list)
{
   bool even = true; // 0th position is even
   foreach (T item in list)
   {
       even = !even;
       if (even)
       {
           yield return item;
       }
   }
}

Am I going extension method crazy??

Collecting Validation Exceptions

I've been putting some thought into validation in the context of an MVC Framework application. Recently I wrote about using Extension Method Validators as a neat way of expressing validation rules in your domain entities. These validators throw a ValidationException when they trigger.

sutekishopValidationErrors

Now in a user interface we would really like to see all the validation failures for a form. So we need to collect the exceptions as they occur and then continue processing. Here's a neat little Validator class that's simply a collection of Action delegates that executes them when its Validate method is called:

public class Validator : List<Action>
{
  public void Validate()
  {
      StringBuilder message = new StringBuilder();

      foreach (Action validation in this)
      {
          try
          {
              validation();
          }
          catch (ValidationException validationException)
          {
              message.AppendFormat("{0}<br />", validationException.Message);
          }
      }

      if (message.Length > 0)
      {
          throw new ValidationException(message.ToString());
      }
  }
}

You can use it like this:

string property = "";

Validator validator = new Validator
{
  () => property.Label("Property 1").IsRequired(),
  () => property.Label("Property 2").IsRequired(),
  () => property.Label("Property 3").IsRequired()
};

validator.Validate();

Since the 'property' variable is an empty string, each call to IsRequired() will throw a ValidationException. The message of each of these exceptions gets captured and then a single ValidationException will be called with the concatenated messages.

Monday, February 11, 2008

Extension method validators

I'm building an MVC Framework application at the moment and I wanted a simple, easy to grep way of validating fields passed back from forms. In MVC-land all the form variables are passed as parameters to the action method. Extension methods turned out to be a very neat solution for doing validation and data conversion. Here's an example:

[ControllerAction]
public void UpdateContact(
    int contactId,
    string name,
    string address1,
    string address2,
    string address3,
    string county,
    string postcode,
    string telephone,
    string email)
{
    try
    {
        name.Label("Name").IsRequired();
        address1.Label("Address 1").IsRequired();
        county.Label("County").IsRequired();
        postcode.Label("Postcode").IsRequired().IsPostcode();
        telephone.Label("Telephone").IsRequired().IsTelephoneNumber();
        email.Label("Email").IsRequired().IsEmail();
    }
    catch (ValidationException exception)
    {
        ContactViewData viewData = ContactViewData(contactId);
        viewData.ErrorMessage = exception.Message;
        RenderView("Contact", viewData);
        return;
    }

 // update the contact and render the view
}

As you can see we pass the contact's details from a form. In the try block the extension method validators are called. Any of them can raise a validation exception which is caught by the catch block and a view is rendered showing the validation error.

The 'Label' extension returns a ValidateField instance that can be consumed by any other validator, this is so that we can raise exceptions that can be displayed directly to the user:

public static ValidateField Label(this string value, string label)
{
    return new ValidateField { Value = value, Label = label };
}

The 'IsRequired' extension takes a ValidateField and checks that the value is not null or empty:

public static ValidateField IsRequired(this ValidateField validateField)
{
    if (string.IsNullOrEmpty(validateField.Value))
    {
        throw new ValidationException(string.Format("{0} is required", validateField.Label));
    }
    return validateField;
}

And finally the 'IsEmail' extension uses a Regex to validate the string value:

public static ValidateField IsEmail(this ValidateField validateField)
{
    // ignore is null or empty, use IsRequired in parrallel to check this if needed
    if (string.IsNullOrEmpty(validateField.Value)) return validateField;

    string patternLenient = @"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*";
    if (!Regex.Match(validateField.Value, patternLenient).Success)
    {
        throw new ValidationException(string.Format("{0} must be a valid email address", validateField.Label));
    }
    return validateField;
}

I'm finding extension methods a real boon for writing DSL-ish APIs. I'll leave the 'IsTelephone' and 'IsPostcode' exercises for your enjoyment :)