Problem with ScopedParams and null values
See original GitHub issueHi,
I use RulesEngine, version 4.0.0 with .NET Core 3.1.
I have a bunch of rules that I simplified using GlobalParams and LocalParams.
The problem I have is that my params refer to array properties of a child object, but, in some situations, this child object may be null. When this occurs, the whole workflow breaks down instead of returning valid values. I would like to know what would be the best practice in that situation.
Here is an example of the input data, the rules I use and the output I get… Please note that I have simplified everything to the smallest meaningful sample… Our real-life objects are much more complex and I have lots of rules, so reusing logic with GlobalParams and LocalParams is a life saver!
Input object:
{
"ActivityId": 1,
"Description": "Activity Description",
"Quote": {
"QuoteId": 1234,
"Items": [{
"ItemId": 1,
"Description": "Product 1",
"Quantity": 2,
"UnitPrice": 1.00
},
{
"ItemId": 2,
"Description": "Product 2",
"Quantity": 1,
"UnitPrice": 10.00
},
]
}
}
Here is the workflow I use:
[
{
"WorkflowName": "Workflow",
"WorkflowRulesToInject": null,
"GlobalParams": [
{
"Name": "PiecesCount",
"Expression": "Activity.Quote == null ? 0d : Activity.Quote.Items.Sum(Quantity)"
}
],
"Rules": [
{
"RuleName": "Load/unload pieces",
"Operator": null,
"ErrorMessage": "Rule failed",
"RuleExpressionType": "LambdaExpression",
"Expression": "PiecesCount != 0",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "PiecesCount * 90d"
}
}
},
"Rules": null
}
]
}
]
For completeness sake, here is how the workflow is run. The rules
variable holds my workflow and the activity
variable holds my input data…
var rulesEngine = new RulesEngine.RulesEngine(rules, new ReSettings()
{
CustomTypes = null,
});
var result = await rulesEngine.ExecuteAllRulesAsync("Workflow",
new RuleParameter("Activity", activity));
When I run this workflow with the sample object provided, The PiecesCount is 3 and the OutputExpression is 270d, as expected.
In some cases, my “activities” have no Quote, like so:
{
"ActivityId": 1,
"Description": "Activity Description",
"Quote": null
}
In that case, I have this error message when the Rule is run:
Error while compiling rule
Load/unload pieces
: No applicable method ‘Sum’ exists in type ‘Object’, in ScopedParam: PiecesCount
I would expect the rule to return 0d, since Activity.Quote == null
(as a reminder, the GlobalParam’s expression is Activity.Quote == null ? 0d : Activity.Quote.Items.Sum(Quantity)
), but it seems the RulesEngine has interpreted the whole expression and failed because the Quote is null.
If my workflow has many rules and some rules never refer to my GlobalParam, all rules fail, even those who don’t refer the param…
For instance, all rules of this workflow fail with the same error message:
[
{
"WorkflowName": "Workflow",
"WorkflowRulesToInject": null,
"GlobalParams": [
{
"Name": "PiecesCount",
"Expression": "Activity.Quote == null ? 0d : Activity.Quote.Items.Sum(Quantity)"
}
],
"Rules": [
{
"RuleName": "Load/unload pieces",
"Operator": null,
"ErrorMessage": "Rule failed",
"RuleExpressionType": "LambdaExpression",
"Expression": "PiecesCount != 0",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "PiecesCount * 90d"
}
}
},
"Rule": null
},
{
"RuleName": "Other unrelated rule",
"Operator": null,
"ErrorMessage": "Rule failed",
"RuleExpressionType": "LambdaExpression",
"Expression": "true == true",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "10d"
}
}
},
"Rules": null
}
]
}
]
Here is the complete response:
[
{
"Rule": {
"RuleName": "Load/unload pieces",
"Properties": null,
"Operator": null,
"ErrorMessage": "Rule failed",
"Enabled": true,
"RuleExpressionType": "LambdaExpression",
"WorkflowsToInject": null,
"Rules": null,
"LocalParams": null,
"Expression": "PiecesCount != 0",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "PiecesCount * 90d"
}
},
"OnFailure": null
},
"SuccessEvent": null
},
"IsSuccess": false,
"ChildResults": null,
"Inputs": {
"Activity": {
"ActivityId": 1,
"Description": "Activity Description",
"Quote": null
}
},
"ActionResult": {
"Output": null,
"Exception": null
},
"ExceptionMessage": "Error while compiling rule `Load/unload pieces`: No applicable method 'Sum' exists in type 'Object', in ScopedParam: PiecesCount"
},
{
"Rule": {
"RuleName": "Other unrelated rule",
"Properties": null,
"Operator": null,
"ErrorMessage": "Rule failed",
"Enabled": true,
"RuleExpressionType": "LambdaExpression",
"WorkflowsToInject": null,
"Rules": null,
"LocalParams": null,
"Expression": "true == true",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "10d"
}
},
"OnFailure": null
},
"SuccessEvent": null
},
"IsSuccess": false,
"ChildResults": null,
"Inputs": {
"Activity": {
"ActivityId": 1,
"Description": "Activity Description",
"Quote": null
}
},
"ActionResult": {
"Output": null,
"Exception": null
},
"ExceptionMessage": "Error while compiling rule `Other unrelated rule`: No applicable method 'Sum' exists in type 'Object', in ScopedParam: PiecesCount"
}
]
Any help / workaround will be much appreciated!
Thanks in advance!
Best regards!
Issue Analytics
- State:
- Created 5 months ago
- Comments:6
Top GitHub Comments
Hi @abbasc52,
A quick follow-up…
I went through my tests again and found out that my test program was using an ExpandoObject.
I updated my test to use a strongly typed object and my basic rules worked!
I’ll rerun through my monster rules and make sure they use strongly typed objects and see if I still face the issue.
I’ll keep you posted of my results.
Thank you again for your help!
Best regards!
Hi @abbasc52,
Sorry for the delay…
Using strongly typed objects solved my issue!
Thank you for your help!
Best regards!