Business rule chaining problem

Business rule chaining problem

Old forum URL: forums.lhotka.net/forums/t/9237.aspx


kennethkryger posted on Wednesday, July 21, 2010

I'm having a little problem with the chaining two business rules.

Basically I've got a class that derives from BusinessBase, that has two properties (PropA and PropB) that needs to be checked. Both of these properties are CSLA properties with managed backing fields.

I need only to evaluate the value of PropB if PropA is not null.

PropA is of the type "MyType" and PropB is an int, that needs to be between 1 and 99.

Here's how I've tried to do just that:

protected override void AddBusinessRules()
{
base.AddBusinessRules();
BusinessRules.AddRule(new PropARule(PropAProperty));
}

 

private class PropARule : BusinessRule
{
private readonly IBusinessRule propBRangeRule;


public LowerPermabilityRule(IPropertyInfo primaryProperty)
base(primaryProperty)
{
InputProperties = new List<IPropertyInfo> { primaryProperty };
propBRangeRule= new PropBRangeRule(PropBProperty);
}
	protected override void Execute(RuleContext context)
{
var myType = (MyType)context.InputPropertyValues[PrimaryProperty];
if (myType != null)
{
propBRangeRule.Execute(context.GetChainedContext(this));
}
}
}
private class PropBRangeRule : BusinessRule
{
public PropBRangeRule(IPropertyInfo primaryProperty)
base(primaryProperty)
{
InputProperties = new List<IPropertyInfo> { primaryProperty };
}

protected override void Execute(RuleContext context)
{
var percentage = (int)context.InputPropertyValues[PrimaryProperty];
if (percentage < 1 || percentage > 99)
{
context.AddErrorResult("Value must be between 1 and 99.");
}
}
}

When I run this, I get a KeyNotFoundException ("The given key was not present in the dictionary.") at this line of code is PropBRangeRule:

var percentage = (int)context.InputPropertyValues[PrimaryProperty];

Also, and this might be related, I'm not sure if this code i PropARule is correct:

propBRangeRule.Execute(context.GetChainedContext(this));

Shoud I use "this" as the variable to pass to the GetChainedContext method? I've looked a Rocky's blogpost here, but that passes a "required" variable to the method, without stating where that variable originates!!??

Any help/pointers is very much appreciated!

Regards,
Kenneth

 

 

Peran replied on Wednesday, July 21, 2010

Hi Kenneth,

There are 2 problems that I can see; firstly with the GetChainedContext, as you said Rockys blog
is not that clear, Rocky maybe you could update?

propBRangeRule.Execute(context.GetChainedContext(***propBRangeRule***));

The method copies the property values from 'this.context' to 'propBRangeRule.context';
which brings me onto the second issue, any property values required for the inner rule B
need to be included in the outer rule A, so that the value is included in the
GetChainedContext copy process.

public LowerPermabilityRule(IPropertyInfo primaryProperty)
base(primaryProperty)
{
InputProperties = new List<IPropertyInfo> { primaryProperty, ***PropBProperty***};
propBRangeRule= new PropBRangeRule(PropBProperty);
}


Hope this helps

Peran


kennethkryger replied on Wednesday, July 21, 2010

Hi Peran,

Thanks for taking a look at my code.
Your suggestion works 99% - which is a great start Smile

I'm no longer getting the KeyNotFoundException, and the only problem I have now, is that the IsValid property of the class that has the business rules (ie. the class where I override the AddBusinessRules-method) is not set to False, even thought the PropBRangeRule's Execute methods sets

context.AddErrorResult("Value must be between 1 and 99.");

Can you se what I'm doing wrong?

Thanks again,
Kenneth

PS. The constructor for PropARule obviously shouldn't have read LowerPermabilityRule - I forgot to change it everywhere, when I was creating the code for this post Embarrassed

Peran replied on Wednesday, July 21, 2010

I would think all the rules in a chain should have the same primary property, so I think you should change your approach.  You could probably replace with a single rule along these lines;

 

private class PropBRangeRule : BusinessRule
{
public PropBRangeRule(IPropertyInfo primaryProperty)
base(primaryProperty)
{
InputProperties = new List<IPropertyInfo> { primaryProperty, PropAProperty };
}

protected override void Execute(RuleContext context)
{
var myType = (MyType)context.InputPropertyValues[PropAProperty];
if (myType != null)
{
var percentage = (int)context.InputPropertyValues[PrimaryProperty];
if (percentage < 1 || percentage > 99)
{
context.AddErrorResult("Value must be between 1 and 99.");
}
}
}
}

 

 

kennethkryger replied on Friday, July 23, 2010

Thank you!
That works!!!

Copyright (c) Marimer LLC