Nesting Validation with configuration file and self validation

Topics: Validation Application Block
Dec 7, 2007 at 3:07 PM
I have a class call "SendTransactionAcceptRejectRequest". This class has a single property call "PaymentMethod" which is of type PaymentMethod.

PaymentMethod contains a single property of object type called "Item". This "Item" can only be assigned one of three specified objects.

I need to be able to nest the following validation:

1. Ensure that PaymentMethod property on a SendTransactionAcceptRejectRequest instance is not null.
2. Ensure that PaymentMethod.Item property is one of the three objects that is allowed.
3. Once this validation has passed, invoke validation on the Item property.

Currently I have attempted to nest this validation using an external configuration file and self validation on the PaymentMethod type. Here is the specified configuration for "SendTransactionAcceptRejectRequest":

<type assemblyName="ntegration.Service.DataContracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
name="Integration.Service.DataContracts.SendTransactionAcceptRejectRequest">
<ruleset name="SendTransactionAcceptRejectRequestRuleSet">
<properties>
<property name="PaymentMethod">
<validator negated="false" messageTemplate="" messageTemplateResourceName=""
messageTemplateResourceType="" tag="" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.NotNullValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
name="Not Null Validator" />
<validator targetRuleset="" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.ObjectValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
name="Object Validator" />
</property>
</properties>
</ruleset>
</type>

Here is the configuration for PaymentMethod:

<type assemblyName="Integration.Service.DataContracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
name="Integration.Service.DataContracts.PaymentMethod">
<ruleset name="PaymentMethodRuleSet" />
</type>

And Here is the configuration for one of the objects that can be assigned to the PaymentMethod.Item property:

<type assemblyName="FCT.LLC.Integration.Service.DataContracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
name="FCT.LLC.Integration.Service.DataContracts.BCOnline">
<ruleset name="BCOnlineRuleSet">
<properties>
<property name="BCOnlineUserFolio">
<validator negated="false" messageTemplate="" messageTemplateResourceName=""
messageTemplateResourceType="" tag="" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.NotNullValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
name="Not Null Validator" />
<validator lowerBound="0" lowerBoundType="Ignore" upperBound="10"
upperBoundType="Inclusive" negated="false" messageTemplate=""
messageTemplateResourceName="" messageTemplateResourceType=""
tag="" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.StringLengthValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
name="String Length Validator" />
</property>
</properties>
</ruleset>
</type>

I have a single unit test:
TestMethod
public void InvalidBCOlineWithRequest()
{
SendTransactionAcceptRejectRequest request = InitializeEmptyRequest();
request.PaymentMethod = new PaymentMethod();
request.PaymentMethod.Item = new BCOnline();

Assert.IsFalse(Validation.ValidateFromConfiguration(request, "SendTransactionAcceptRejectRequestRuleSet").IsValid);
}

Essentially what I expect to happen when this test method is called is:

1. Validation is invoked on the "SendTransactionAcceptRejectRequest" request.
2. As the PaymentMethod is examined two validators are fired "not null validator" and "object validator". This should allow for any validation on the PaymentMethod object to be fired.
3. Using the self validation functionality defined in the PaymentMethod class:

HasSelfValidation
public partial class PaymentMethod
{
SelfValidation
public void CheckPaymentType(ValidationResults results)
{
string[] choices = new string[] {typeof(CardDetail).ToString(), typeof(BCOnline).ToString(), typeof(string).ToString() };
bool found = false;

foreach (string obj in choices)
{
if (Item.GetType().ToString().Equals(obj))
{
found = true;
break;
}
}

if(!found)
{
results.AddResult(new ValidationResult("Payment Method property is not of correct type.", this, "Test1", null, null));
}
else
{
results.AddAllResults(Validation.ValidateFromConfiguration(Item));
}
}
}

I check to see if the object assigned to the Item property is one of the three that can be assigned to this property. If validation is successful, I then attempt to validate on that actual object (in this case "BCOnline") which should in turn invoke the validation from the configuration for this type.

This is where I am having the problem. I can get past the first two steps: Validating on the parent object, and performing the self validation check on the PaymentMethod object, but when I attempt to validate on the actual object for the Item property, the validation result is always true (which it shouldn't be). I need to know what I might be missing here (particularly through using the configuration file). I have tried several different scenarios, but each time validation for the Item property comes back true.

What is even more puzzling is that another unit test I have to just test validation on the BCOnline object works fine:

TestMethod
public void ValidBCOnline()
{
BCOnline o = new BCOnline();
o.BCOnlineUserFolio = "test";
Assert.IsTrue(Validation.ValidateFromConfiguration(o, "BCOnlineRuleSet").IsValid);
}

Any help, feedback, good article on nesting validation using config file would be sincerely appreciated.