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
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
Hi Peran,
Thanks for taking a look at my code.
Your suggestion works 99% - which is a great start
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
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.");
}
}
}
}
Thank you!
That works!!!
Copyright (c) Marimer LLC