Print

Using IDataErrorInfo with Validation Application Block

The IDataErrorInfo interface is a core part of the .NET framework and both WPF and ASP.NET MVC use this interface for validation purposes. In this article I will show how to build an abstract base class that implements IDataErrorInfo in a way that Validation Application Block is used under the covers.

Using the IDataErrorInfo interface on domain or ViewModel objects is one of the ways to leaverage validation in UI technologies such as WPF and ASP.NET MVC. Having to implement that interface (with its properties) on each and every ViewModel or domain object however, is quite cumbersome and is certainly not DRY. It is much more convenient to use a base class that implements everything you need. This way, instead of having to implement the complete IDataErrorInfo interface, we can simply inherit from this base class:

public partial class Customer : DataErrorInfo
{
}

Below is the code for the DataErrorInfo class. If you look closely you will see a couple of interesting things. First of all, the IDataErrorInfo interface members are implemented explicitly to prevent them from showing up using IntelliSense, because they have no other purpose than for validation by a UI technology. Next, the code uses VAB’s PropertyValidationFactory to ensure only the requested property is validated. Not only is this more efficient than validating the complete entity, it also prevents us from having to figure out which errors are caused by that particular property.

public abstract class DataErrorInfo : IDataErrorInfo
{
string IDataErrorInfo.Error
{
get { return DataErrorInfoHelper.GetErrorInfo(this); }
}

string IDataErrorInfo.this[string columnName]
{
get { return DataErrorInfoHelper.GetErrorInfo(this, columnName); }
}
}

public static class DataErrorInfoHelper
{
public static string GetErrorInfo(object entity)
{
var type = entity.GetType();
var validator =
ValidationFactory.CreateValidator(type);
var results = validator.Validate(entity);
return String.Join(" ",
results.Select(r => r.Message).ToArray());
}

public static string GetErrorInfo(object entity,
string propertyName)
{
PropertyInfo property =
entity.GetType().GetProperty(propertyName);

return GetErrorInfo(entity, property);
}

public static string GetErrorInfo(object entity,
PropertyInfo property)
{
var validator = GetPropertyValidator(entity,
property);

if (validator != null)
{
var results = validator.Validate(entity);

return String.Join(" ",
results.Select(r => r.Message).ToArray());
}

return string.Empty;
}

private static Validator GetPropertyValidator(
object entity, PropertyInfo property)
{
string ruleset = string.Empty;
var source = ValidationSpecificationSource.All;
var builder = new ReflectionMemberValueAccessBuilder();

return PropertyValidationFactory.GetPropertyValidator(
entity.GetType(), property, ruleset, source, builder);
}
}

When you are in the unlucky position of using Entity Framework 3.5 (my condolences btw), you are stuck to inheriting your entities from EntityObject or ComplexObject. In that case, you need to define the partial class as follows:

public partial class Customer : IDataErrorInfo
{
string IDataErrorInfo.Error
{
get { return DataErrorInfoHelper.GetErrorInfo(this); }
}

string IDataErrorInfo.this[string columnName]
{
get { return DataErrorInfoHelper.GetErrorInfo(this, columnName); }
}
}

In other words, you can't inherit from a base type, but must implement IDataErrorInfo directly and implement the interface members in each type.

Happy validating.

- .NET General, C#, Enterprise Library, Validation Application Block - five comments / No trackbacks - §

The code samples on my weblog are colorized using javascript, but you disabled javascript (for my website) on your browser. If you're interested in viewing the posted code snippets in color, please enable javascript.

five comments:

This is very great!!
Thank you!
Sven - 21 04 11 - 09:58

Very nice
Eric - 06 06 11 - 05:12

thanks.

you're missing the "this" keyword in your extension method..should be

private static Validator GetPropertyValidator(this object entity, PropertyInfo property)
Justin - 13 03 12 - 21:35

Thanks Justin,

I fixed the bug.
Steven (URL) - 13 03 12 - 21:41

Welcome! Nike Air Max Shoes Pas Cher .FR,Store Online, "Health & Lifestyle" . Sale All kinds of Nike Air Max shoes, with nike air max 90, nike air max 95,nike air max 2012,nike air max 2011,nike air max pas cher etc. http://www.nikeairmaxot.com.
Nike Air Max Shoes (URL) - 18 04 12 - 09:57


No trackbacks:

Trackback link:

Please enable javascript to generate a trackback url


  
Remember personal info?

/

Before sending a comment, you have to answer correctly a simple question everyone knows the answer to. This completely baffles automated spam bots.
 

  (Register your username / Log in)

Notify:
Hide email:

Small print: All html tags except <b> and <i> will be removed from your comment. You can make links by just typing the url or mail-address.