Rulesets with nested objects

Topics: Validation Application Block
Mar 8, 2013 at 3:35 PM
I'm having a problem applying Rulesets when validating objects with nested objects when using Enterpirse Library validation. If I have the following objects
public class Person
{
    [ObjectValidator]
    [ObjectValidator(Ruleset = "A")]
    public Address Address  { get; set; }
}

public class Address  
{
    [StringLengthValidator(0, 32, MessageTemplate = "Invalid value '{0}' for {1}, Max length:{5}")]
    public string Address1 { get; set; }

    [StringLengthValidator(0, 32, MessageTemplate = "Invalid value '{0}' for {1}, Max length:{5}", Ruleset = "A")]
    public string Address2 { get; set; }
}
Now if I try to validate the object by calling
ValidationResults results = Validation.Validate(myPersonObject);
I get my default validation as expected, i.e if Person.Address.Address1 is too long it fires but Person.Address.Address2 is ignored, this is as expected.

However if I try to invoke my validation for Ruleset "A" as follows
ValidationResults results = Validation.Validate(myPersonObject, "A");
I always get the same results as the previous validate call despite the fact I have specified the Ruleset. Any suggestions?
Mar 10, 2013 at 1:45 AM
Edited May 1, 2013 at 9:39 PM
I'm going to call this a non-intuitive "behavior".

You need to specify the Ruleset name in the constructor as well as to the Ruleset named parameter:
    public class Person
    {
        [ObjectValidator]
        [ObjectValidator("A", Ruleset = "A")]
        public Address Address { get; set; }
    }
The constructor argument is the target ruleset in the target object ("Address") while the Ruleset named parameter is what the ruleset is called on the current object ("Person").

So the two ruleset names don't have to even match. For example you could define the ruleset as "A" in Person but target a ruleset named "AB" in Address:
    public class Person
    {
        [ObjectValidator]
        [ObjectValidator("AB", Ruleset = "A")]
        public Address Address { get; set; }
    }
   
    public class Address
    {
        [StringLengthValidator(0, 32, MessageTemplate = "Invalid value '{0}' for {1}, Max length:{5}")]
        public string Address1 { get; set; }

        [StringLengthValidator(0, 32, MessageTemplate = "Invalid value '{0}' for {1}, Max length:{5}", Ruleset = "AB")]
        public string Address2 { get; set; }
    }

    ValidationResults results = Validation.Validate(myPersonObject, "A");
There is already a work item for this issue although I think it may be working as designed (even though it is a bit confusing).

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Mar 10, 2013 at 7:30 PM
Ah ok, I guess that makes sense now that you've explained it :)
Thanks Randy