Subject: Query Regarding RulesEngine: Execution error - "Unable to cast object of type 'System.Linq.Expressions.InstanceMethodCallExpression1' t.o type 'System.Linq.Expressions.ParameterExpression"
Hello,
I am writing to seek assistance regarding an issue we are encountering while using the RulesEngine. We have a RulesExpression with multiple rules, where the output of one rule is used as input for another rule. However, we are experiencing an error during the execution of the second rule's expression.
Here are the details of our RulesExpression:
{
"RuleExpression": [
{
"WorkflowName": "DataBuilder",
"Rules": [
{
"RuleName": "GetAuthorDetails",
"Expression": "input1.ApiOutputs.FirstOrDefault(x => x.ExternalApiIdentifier == \"NessieSearchPeopleApi\") != null",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "input1.ApiOutputs.FirstOrDefault(x => x.ExternalApiIdentifier == \"NessieSearchPeopleApi\").Input.people"
}
}
}
}
]
},
{
"WorkflowName": "DataBuilder",
"Rules": [
{
"RuleName": "GetAuthorDetails",
"Expression": "input2 != null",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "input2.FirstOrDefault(x => x.fullName != null);"
}
}
}
}
]
}
]
}
We have a C# code snippet that parses and executes the rules:
var newInput = new Object();
var workflows = JsonConvert.DeserializeObject<List<Workflow>>(payload.RuleExpression.ToString());
foreach (var workflow in workflows)
{
var workflowList = new List<Workflow>();
workflowList.Add(workflow);
var bre = new RulesEngine.RulesEngine(workflowList.ToArray(), null);
List<RuleResultTree> resultList = bre.ExecuteAllRulesAsync("DataBuilder", resolverInput, newInput).Result;
var resultFromRule = resultList[0].ActionResult.Output;
newInput = resultFromRule;
}
During the execution of the second rule's expression, we are encountering the following error: 'Exception while executing OutputExpressionAction: Unable to cast object of type 'System.Linq.Expressions.InstanceMethodCallExpression1' to type 'System.Linq.Expressions.ParameterExpression'.'
The error occurs specifically in the expression: "Expression": "input2.FirstOrDefault(x => x.fullName != null);"
We would greatly appreciate any insights, suggestions, or guidance on how to resolve this error and successfully execute the second rule's expression.
Thank you in advance for your assistance. Best regards, Amina
Hello,
Attached Rules Schema and Code Snippet are not clear:
-
Rules Schema : Looks wrong for me when I look at "RuleExpression": [ --- Please find example for RulesSchema at https://github.com/microsoft/RulesEngine/wiki/Getting-Started#rules-schema
-
Code Snippet: Not showing clearly the final object of newInput . Just showing var newInput = new Object(); Not sure whether this holds any property with collection of objects.
Please find here sample unit test code snippet, the one it's matching with your scenario:
Test Case: RulesEngine_Execute_Rule_For_Nested_Rule_Params_Returns_Success
Test Class: https://github.com/microsoft/RulesEngine/blob/main/test/RulesEngine.UnitTest/BusinessRuleEngineTest.cs
Test Data: https://github.com/microsoft/RulesEngine/blob/main/test/RulesEngine.UnitTest/TestData/rules4.json
I hope it's helps to resolve your issue.
Cheerio Prasad RAMIREDDY
Hi
Sorry for the confusion
Here are the Rules Schema and inputs used for executing the expressions
1 - Rules Schema
[
{
"WorkflowName": "DataBuilder",
"Rules": [
{
"RuleName": "GetAuthorDetails",
"Expression": "input1.ApiOutputs.FirstOrDefault(x => x.ExternalApiIdentifier == \"NessieSearchPeopleApi\") != null",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "input1.ApiOutputs.FirstOrDefault(x => x.ExternalApiIdentifier == \"NessieSearchPeopleApi\").Input.people"
}
}
}
}
]
},
{
"WorkflowName": "DataBuilder",
"Rules": [
{
"RuleName": "GetAuthorDetails",
"Expression": "input2 != null",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "input2.FirstOrDefault(x => x.fullName != null);"
}
}
}
}
]
}
]
2 - input1.ApiOutputs used in the first expression
"Expression": "input1.ApiOutputs.FirstOrDefault(x => x.ExternalApiIdentifier == "NessieSearchPeopleApi").Input.people",
[
{
"ExternalApiIdentifier": "NessieSearchPeopleApi",
"JobUId": "e18ab695-9bf0-4b64-8bf4-36cf67d5f1e6",
"Input": {
"people": [
{
"queryId": "27179be6-1db9-4e4f-8fc6-c309825a43d5",
"emails": [
"[email protected]"
],
"fullName": "FrontiersinGenetics",
"affiliations": [
{
"id": 241183997,
"name": "FrontiersMediaSA",
"countryName": "Switzerland"
}
]
},
{
"queryId": "27179be6-1db9-4e4f-8fc6-c309825a43d5",
"emails": [
"[email protected]"
],
"fullName": null,
"affiliations": [
{
"id": 241183997,
"name": "FrontiersMediaSA",
"countryName": "Switzerland"
}
]
}
],
"filters": {
"exclusionCategories": []
},
"results": {
"unknownThreshold": 1,
"maxResults": 1
},
"applicationName": "JournalAIRAQualityCheck"
},
"Processed": true,
"Message": null,
"ResponseContent": []
}
]
3 - input2 We are using the output of this first expression as input2 of the second expression and it is defined as an object that is strored in the newInput of the code
{[input2, {[
{
"queryId": "27179be6-1db9-4e4f-8fc6-c309825a43d5",
"emails": [
"[email protected]"
],
"fullName": "FrontiersinGenetics",
"affiliations": [
{
"id": 241183997,
"name": "FrontiersMediaSA",
"countryName": "Switzerland"
}
]
},
{
"queryId": "27179be6-1db9-4e4f-8fc6-c309825a43d5",
"emails": [
"[email protected]"
],
"fullName": null,
"affiliations": [
{
"id": 241183997,
"name": "FrontiersMediaSA",
"countryName": "Switzerland"
}
]
}
]}]}
Here is the expression we are getting the error
input2.FirstOrDefault(x => x.fullName != null)
@Amina-2310 not sure if it is a typo but can you try after removing the trailing semicolon here:
input2.FirstOrDefault(x => x.fullName != null);
Hi I have tried with removing semicolon. But still same issue is there.
It's working for me after typo correction. @Amina-2310 May be Visual Studio cache issue. Clean the solution and run again.
I tested with: [ { "WorkflowName": "DataBuilder", "Rules": [ { "RuleName": "GetAuthorDetails", "Expression": "input1.ApiOutputs.FirstOrDefault(x => x.ExternalApiIdentifier == "NessieSearchPeopleApi") != null", "Actions": { "OnSuccess": { "Name": "OutputExpression", "Context": { "Expression": "input1.ApiOutputs.FirstOrDefault(x => x.ExternalApiIdentifier == "NessieSearchPeopleApi").Input.people" } } } } ] }, { "WorkflowName": "DataBuilder", "Rules": [ { "RuleName": "GetAuthorDetails", "Expression": "input2 != null", "Actions": { "OnSuccess": { "Name": "OutputExpression", "Context": { "Expression": "input2.FirstOrDefault(x => x.fullName != null)" } } } } ] } ]
With Test Data: Input 1: [ { "WorkflowName": "DataBuilder", "Rules": [ { "RuleName": "GetAuthorDetails", "Expression": "input1.ApiOutputs.FirstOrDefault(x => x.ExternalApiIdentifier == "NessieSearchPeopleApi") != null", "Actions": { "OnSuccess": { "Name": "OutputExpression", "Context": { "Expression": "input1.ApiOutputs.FirstOrDefault(x => x.ExternalApiIdentifier == "NessieSearchPeopleApi").Input.people" } } } } ] }, { "WorkflowName": "DataBuilder", "Rules": [ { "RuleName": "GetAuthorDetails", "Expression": "input2 != null", "Actions": { "OnSuccess": { "Name": "OutputExpression", "Context": { "Expression": "input2.FirstOrDefault(x => x.fullName != null)" } } } } ] } ]
Input 2: [ { "queryId": "27179be6-1db9-4e4f-8fc6-c309825a43d5", "emails": [ "[email protected]" ], "fullName": "FrontiersinGenetics", "affiliations": [ { "id": 241183997, "name": "FrontiersMediaSA", "countryName": "Switzerland" } ] }, { "queryId": "27179be6-1db9-4e4f-8fc6-c309825a43d5", "emails": [ "[email protected]" ], "fullName": null, "affiliations": [ { "id": 241183997, "name": "FrontiersMediaSA", "countryName": "Switzerland" } ] } ]
Hi
Could you please confirm that input2 is stored as an object rather than a model.
var newInput = new Object();
var workflows = JsonConvert.DeserializeObject<List<Workflow>>(payload.RuleExpression.ToString());
foreach (var workflow in workflows)
{
var workflowList = new List<Workflow>();
workflowList.Add(workflow);
var bre = new RulesEngine.RulesEngine(workflowList.ToArray(), null);
List<RuleResultTree> resultList = bre.ExecuteAllRulesAsync("DataBuilder", resolverInput, newInput).Result;
var resultFromRule = resultList[0].ActionResult.Output;
newInput = resultFromRule;
}
this is the code for executing the expression . Here input2 is the result of first expression and is treated as an object
Hi @pramireddy, May I know if you had an opportunity to review the last point made by Amina?
@Amina-2310. Could you try using dynamic newInput = new Object();
RulesEngine requires Inputs of either strong type or ExpandoObject