views:

9

answers:

1

I've run into a bit of a wall in trying to use the .NET DataAnnotations feature to provide simple validations in a derived class. I am marking up my class with the standard annotations included in .NET 4 (from the System.ComponentModel.DataAnnotations namespace), then using the MS Enterprise Library v5 Validation Block to process the rules.

I have a number of objects derived from a common base class, which contains properties common to all of my objects. For validation purposes, I may have different rules for the various classes derived from this class.

Here's a simplified example:

public abstract class PersonBase
{
    public int Id { get; set; }
    public string Name { get; set; }
}

[MetadataType(typeof(CustomerMD))]
public class Customer : PersonBase
{

}
[MetadataType(typeof(ManagerMD))]
public class Manager : PersonBase
{

}

public class CustomerMD
{
    [Required]
    [StringLength(20, ErrorMessage="Customer names may not be longer than 20 characters.")]
    public object Name { get; set; }
}

public class ManagerMD
{
    [Required]
    [StringLength(30, ErrorMessage = "Manager names may not be longer than 30 characters.")]
    public object Name { get; set; }
}

// calling code
var invalidCustomer = new Customer {Id=1, Name=string.Empty};
var valFactory = EnterpriseLibraryContainer.Current.GetInstance<ValidatorFactory>();
var customerValidator = valFactory.CreateValidator<Customer>();
var validationResults = customerValidator.Validate(invalidCustomer);
// validationResults.IsValid should equal False, but actually equals True.

I have found that I can get the expected validation results if I push the annotations down to the base class, but then I lose the ability to fulfill different requirements for different types. Also, if I put class-specific properties on a derived class and provide metadata for these properties, I get results, but only for these properties, not the properties from the base class.

I haven't yet tried using the EntLib provided validation attributes; I'd prefer to keep the library this lives in free of dependencies from outside the core framework, if at all possible.

Am I missing something, or am I just out of luck here?

A: 

I think I have a workable solution for this.

It appears that the Metadata class will not provide validation of properties belonging to the superclass of the target object. In order to get Metadata to work with this, I needed to mark the superclass properties as virtual, then provide overrides for the properties that I wanted to validate.

Example (see question above for original example):

public abstract class PersonBase
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
}
[MetadataType(typeof(CustomerMD))]
partial class Customer : PersonBase
{
    public override string Name
    {
        get
        {
            return base.Name;
        }
        set
        {
            base.Name = value;
        }
    }
}

With the override in place, the validator works as expected. It's a little more work, but it will get the job done.

I also tried adding annotations to the base class as fallback default rules; this allows me to have a base set of rules and override them as needed on a case by case basis. Looking good.

Scroll Lock