×
Namespaces

Variants
Actions

Data validation using Fluent Validation in Windows Phone

From Nokia Developer Wiki
Jump to: navigation, search
Featured Article
15 Dec
2013

This article explains how to validate data in Windows Phone 8 using the Fluent Validation library.

WP Metro Icon File.png
SignpostIcon XAML 40.png
WP Metro Icon WP8.png
Article Metadata
Code Example
Source file: SkyDrive
Tested with
SDK: Windows Phone 8.0 SDK
Devices(s): Emulator, Lumia 1020
Compatibility
Platform(s):
Windows Phone 8
Dependencies: MVVM Light, Fluent Validation 5.0
Article
Created: NicoVermeir (02 Dec 2013)
Last edited: kiran10182 (15 Dec 2013)

Contents

Introduction

Data validation is required almost everywhere an app takes data input. There are many approaches for Sliverlight/WPF and most of them will also work in Windows Phone.

This code example explains how to use the Fluent Validation library (available on Nuget), which describes itself as "a small validation library for .NET that uses a fluent interface and lambda expressions for building validation rules for your business objects". The library is simple to use and makes it very easy to define complex but readable validation rules.

The demo app is a simple user registration form into which a user can enter their name, birth date and country. The example integrates with the MVVM Light Toolkit and its SimpleIoc. The Fluent Validation codeplex page has additional examples.

Adding the package

We start of with an empty solution, add the MVVM Light libraries, bind the datacontext of MainPage to MainViewModel in the normal way. Once the MVVM setup is complete it’s time to add the Fluent Validation package to the project.

Install-Package FluentValidation

Fluent Validation is an open source project available on Codeplex

The settings of the portable class library are shown below. Note, the implementation below will work just as well on Windows Store apps!

Portable Class Library properties

The full set of libraries supported by Fluent Validation is: .NET 4.0, MVC 3, MVC 4, MVC 5, Portable

Creating the model

There is only one model class in this app, called Member. This defines the user's name, birth date, and country.

public class Member
{
public string Name { get; set; }
public DateTime BirthDate { get; set; }
public string Country { get; set; }
}

Setting up the validation

There is some work involved in getting everything setup. Don’t worry, it's not rocket science.

First create a ValidatorFactory. This is needed because we use SimpleIoc to inject the validators into the ViewModels.

Tip.pngTip: If you don’t want to do this you can just create the validators and instantiate them whenever you need one, the Codeplex page of Fluent Validation has great documentation on this.

A ValidatorFactory class inherits from the ValidatorFactoryBase class included in the library.

public class ValidatorFactory : ValidatorFactoryBase
{
public ValidatorFactory()
{
//register the Validators
SimpleIoc.Default.Register<IValidator<Member>, MemberValidator>();
}
 
public override IValidator CreateInstance(Type validatorType)
{
return SimpleIoc.Default.GetInstance(validatorType) as IValidator;
}
}

The constructor of the ValidatorFactory is where all validators are being registering. You could do this in the ViewModelLocator as well, like any other class / repository / viewmodel, but this keeps the ViewModelLocator cleaner and keeps the validation logic a bit closer together.

The CreateInstance function needs to be overridden and returns the instance of the requested validator.

Building a validator

In this step we’re building a validator for the Member class. A validator inherits from AbstractValidator<T> where T is the class you want to validate.

public class MemberValidator : AbstractValidator<Member>
{
public MemberValidator()
{
RuleFor(member => member.Name).NotEmpty();
RuleFor(member => member.BirthDate).LessThan(DateTime.Today);
}
}

In the constructor of the validator we can finally start to add some rules. In this case we’re saying that the Name property should not be empty and that the BirthDate property should be before today’s date.

We'll need to register this class into our IOC, so in ViewModelLocator add this line:

SimpleIoc.Default.Register<ValidatorFactory>(true);

We pass in true as parameter to make sure the object is instantiated at the moment of registration, that way all validators are registered in the IOC as well (as seen in the ValidatorFactory's constructor).

As a reference, these are all the built in validators

  • NotNull
  • NotEmpty
  • NotEqual
  • Equal
  • Length
  • LessThan
  • LessThanOrEqual
  • GreaterThan
  • GreaterThanOrEqual
  • Predicate
  • RegEx
  • Email


Quite an impressive list, and probably most of what developers will need. Just in case that the one that you need isn't included, you can build your own, we'll discuss that in a bit. Let’s get these rules to work first.

Validating data

At this point there is a a factory and validator, and they are all are getting registered in our IOC. Now we hook up the ViewModels and start validating.

In the MainViewModel add a property of type Member to bind against

private Member _newMember;
public Member NewMember
{
get { return _newMember; }
set
{
if (_newMember == value) return;
 
_newMember = value;
 
RaisePropertyChanged(() => NewMember);
}
}

Next, we'll add two fields, one for the validator and one for the save command

private ICommand _saveMemberCommand;
private IValidator<Member> _validator;

Next up is the ICommand property for the Save Command

public ICommand SaveMemberCommand
{
get { return _saveMemberCommand ?? (_saveMemberCommand = new RelayCommand(SaveMember)); }
}

Before we dive into the SaveMember method, we'll need to do some constructor injection and initialization.

public MainViewModel(ValidatorFactory validator)
{
NewMember = new Member
{
BirthDate = DateTime.Today
};
 
_validator = validator.GetValidator<Member>();
}

As a parameter we get our ValidatorFactory, using its GetValidator<T> function we can fill up the _validator field. NewMember gets instantiated and the BirthDate property is set to a default of today.

And last but not least, the SaveMember method

private void SaveMember()
{
if (IsValid())
{
MessageBox.Show("Registration completed!");
}
}
 
private bool IsValid()
{
ValidationResult validationResult = _validator.Validate(NewMember);
 
if (!validationResult.IsValid)
{
ShowErrors(validationResult.Errors);
 
return false;
}
 
return true;
}
 
private void ShowErrors(IEnumerable<ValidationFailure> errors)
{
StringBuilder builder = new StringBuilder();
 
builder.AppendLine("The following errors occured:");
foreach (ValidationFailure error in errors)
{
builder.AppendLine("- " + error.ErrorMessage);
}
 
MessageBox.Show(builder.ToString(), "error", MessageBoxButton.OK);
}

To validate an instance we call the Validate() function on a validator for that type, in this case "Member". That function returns a ValidationResult. ValidationResult contains a bool property IsValid and a list of errors that it found.

We iterate over this list and put every error into a StringBuilder to get a nice error message in a MessageBox. If I try to save with an empty name and today’s date as birth date I get this.

Validation errors

Our validation is working! But those messages could be a bit better. Fluent Validator provides us with options to adjust the property name or the entire message. Change the constructor of the MemberValidator to this.

public MemberValidator()
{
RuleFor(member => member.Name).NotEmpty().WithMessage("You should enter your name");
RuleFor(member => member.BirthDate).LessThan(DateTime.Today).WithName("date of birth");
}

On line 3 we use .WithMessage(“”) to replace the default message by whatever we want. Line 4 replaces the default name of the property, the result is similar yet slightly different.

Custom message error

Adding a custom validator

Let’s say that we want to add validation to the Country property. This property must have a value of either ‘Belgium’, ‘Netherlands’ or ‘Luxemburg’ (this is called the BeNeLux). Obviously, this isn’t included as one simple validator so we’ll just build it ourselves.

We’ll need a class that inherits from PropertyValidator and overrides the IsValid function.

public class CountryMustBeInBenelux : PropertyValidator
{
public CountryMustBeInBenelux()
: base("{PropertyName} is not a Benelux country")
{
 
}
 
protected override bool IsValid(PropertyValidatorContext context)
{
if (context.PropertyValue == null)
return false;
 
string country = context.PropertyValue.ToString().ToLower();
 
return country == "belgium" || country == "netherlands" || country == "luxemburg";
}
}

The string that we pass in to the base constructor is the default message that will be used for this validator. The IsValid function takes a parameter of PropertyValidatorContext. This will contain the property that we want to validate and its value.

Next, in the MemberValidator constructor we add the validation for the Country property.

public MemberValidator()
{
RuleFor(member => member.Name).NotEmpty().WithMessage("You should enter your name");
RuleFor(member => member.BirthDate).LessThan(DateTime.Today).WithName("date of birth");
 
RuleFor(member => member.Country).SetValidator(new CountryMustBeInBenelux());
}

As you can see we need to use the SetValidator function to add our own validator.

The result now is this (I’ve entered a name and a valid birthdate to clean up the error list a bit)

Custom validator error

Summary

In this article I've discussed the use of Fluent Validator to do data validation in Windows Phone 8 apps. I’ve used the portable version of the library so these examples should work just fine on Windows 8 as well.

The Fluent Validator library has many more options than what I've discussed here and they are all well documented, head over the the Codeplex page if you want to do more and deeper validation.

Note.pngNote: This article was originally posted in Nico's Blog

This page was last modified on 15 December 2013, at 15:12.
298 page views in the last 30 days.
×