Skip to content

documentation #30

Closed
Closed

Description

@asulwer

Examples, comments and documentation are grossly lacking. if anyone is to use this repository each feature needs to be documented

Activity

  1. self-assigned this
    on Jun 29, 2024
  2. RenanCarlosPereira commented on Jun 30, 2024

    @RenanCarlosPereira
    Collaborator

    please check out the documentation on the original website:
    https://microsoft.github.io/RulesEngine/

    this content is in the folder doc, and it has most of the documentation to use the tool.
    to
    create our website we need to do the same with GitHub pages

  3. asulwer commented on Jul 1, 2024

    @asulwer
    OwnerAuthor

    in my opinion the documentation touches on the basics. what is missed is a lot. example, is missing Actions. i am just saying that we need better documentation which has been something users of RulesEngine have always complained about.

  4. RenanCarlosPereira commented on Jul 1, 2024

    @RenanCarlosPereira
    Collaborator

    Nice, so what exactly are we missing in the documentation?

    Would be nice to know so we can work on it.

    A valid good point is how to create expressions, but we can see it here:

    https://dynamic-linq.net/expression-language#operators

  5. asulwer commented on Jul 1, 2024

    @asulwer
    OwnerAuthor

    expressions are 'sort of' created for us., something i want to fix, seems hardcoded at the moment

  6. asulwer commented on Jul 4, 2024

    @asulwer
    OwnerAuthor

    @RenanCarlosPereira

    1. wiki links in readme are broken. i need to setup the wiki so those links work.
    2. document changes that were added in regard to methods with CancellationToken as a parameter
  7. uBoscuBo commented on Jul 15, 2024

    @uBoscuBo

    If anyone can provide better insights (e.g., documentation/examples) on utilizing "OnSuccess or OnFailure," that would be splendid. Specifically, how to deserialize a JSON, as shown in the picture, is where I am stuck.

    Json File:

    { "WorkflowName": "inputWorkflow", "Rules": [ { "RuleName": "GiveDiscount20Percent", "Expression": "input1.couy == \"india\" AND input1.loyalityFactor <= 5 AND input1.totalPurchasesToDate >= 20000", "Actions": { "OnSuccess": { "Name": "OutputExpression", //Name of action you want to call "Context": { //This is passed to the action as action context "Expression": "input1.TotalBilled * 0.8" } }, "OnFailure": { // This will execute if the Rule evaluates to failure "Name": "EvaluateRule", "Context": { "WorkflowName": "inputWorkflow", "ruleName": "GiveDiscount10Percent" } } } }, { "RuleName": "GiveDiscount10Percent", "SuccessEvent": "10", "ErrorMessage": "One or more adjust rules failed.", "ErrorType": "Error", "RuleExpressionType": "LambdaExpression", "Expression": "input1.couy == \"india\" AND input1.loyalityFactor <= 2 AND input1.totalPurchasesToDate >= 5000 AND input2.totalOrders > 2 AND input2.noOfVisitsPerMonth > 2", "Actions": { "OnSuccess": { "Name": "OutputExpression", //Name of action you want to call "Context": { //This is passed to the action as action context "Expression": "input1.TotalBilled * 0.9" } } } } ] }

    Code:
    `

    string? json = File.ReadAllText(FileDirectory!);
    json = json.Replace("\r\n", "").Replace("\\", "").Trim();
    var rule = JsonSerializer.Deserialize<Workflow>(json);
    var rules = new List<Workflow> { rule! };
    var re = new RulesEngine.RulesEngine(rules.ToArray());
    
    var input = new RuleParameter("input1", new
    {
        couy = "india",
        loyalityFactor = 2,
        totalPurchasesToDate = 40000,
        totalOrders = 3,
        noOfVisitsPerMonth = 3,
        TotalBilled = 2000
    });
    
    var result = await re.ExecuteActionWorkflowAsync("inputWorkflow", "GiveDiscount20Percent", new List<RuleParameter> { input }.ToArray());
    
    Console.WriteLine(result);`
    

    Error:
    System.Text.Json.JsonException
    HResult=0x80131500
    Message='i' is invalid after a value. Expected either ',', '}', or ']'. Path: $.Rules[0] | LineNumber: 0 | BytePositionInLine: 131.
    Source=System.Text.Json
    StackTrace:
    at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, JsonReaderException ex)
    at System.Text.Json.Serialization.JsonConverter1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state) at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan1 utf8Json, JsonTypeInfo1 jsonTypeInfo, Nullable1 actualByteCount)
    at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan1 json, JsonTypeInfo1 jsonTypeInfo)
    at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options)
    at RuleBasedEngineLibrary.RuleEngineWrapper.d__5.MoveNext() in C:\Users\E1365537\Desktop\RuleBasedEngineApp\RuleBasedEngineLibrary\RuleEngineWrapper.cs:line 19
    at Program.<

    $>d__0.MoveNext() in C:\Users\E1365537\Desktop\RuleBasedEngineApp\ConsoleApp\Program.cs:line 9

    This exception was originally thrown at this call stack:
    [External Code]

    Inner Exception 1:
    JsonReaderException: 'i' is invalid after a value. Expected either ',', '}', or ']'. LineNumber: 0 | BytePositionInLine: 131.

  8. asulwer commented on Jul 15, 2024

    @asulwer
    OwnerAuthor

    @uBoscuBo could you please edit your comment to include that code and not an image of it?

  9. uBoscuBo commented on Jul 16, 2024

    @uBoscuBo

    @asulwer It is updated. This example is from the Rule Engine website, given here

  10. RenanCarlosPereira commented on Jul 16, 2024

    @RenanCarlosPereira
    Collaborator

    @uBoscuBo, I understand the issue you're experiencing. This problem is related to JSON deserialization rather than the rules engine itself. Specifically, System.Text.Json does not natively handle comments within JSON files, which causes the deserialization process to fail.

    note that you don't need to replace anything in the example, as we have to have double quotes in for example this case
    "input1.couy == \"india\" AND input1.loyalityFactor <= 5 AND input1.totalPurchasesToDate >= 20000"

    To resolve this issue, you have two options:

    1. Remove Comments from JSON: Manually remove any comments from your JSON file before attempting to deserialize it.

    2. Configure JsonSerializerOptions to Skip Comments: You can configure the JsonSerializerOptions to ignore comments during deserialization. Here’s how you can modify your code:

      var data = File.ReadAllText("workflow.json");
      var options = new JsonSerializerOptions
      {
          ReadCommentHandling = JsonCommentHandling.Skip
      };
      var workflow = JsonSerializer.Deserialize<Workflow>(data, options)!;

    By setting ReadCommentHandling to JsonCommentHandling.Skip, the deserializer will ignore any comments in the JSON and successfully parse the remaining content.

    I hope this helps! If you have any further questions, feel free to ask.


  11. uBoscuBo commented on Jul 19, 2024

    @uBoscuBo

    @RenanCarlosPereira - Thanks for the heads up. That solved that one issue, but now I am getting the following error.

    System.Text.Json.JsonException: 'The JSON value could not be converted to RulesEngine.Models.RuleExpressionType. Path: $.Rules[1].RuleExpressionType | LineNumber: 27 | BytePositionInLine: 46.'

    Was there a change to the schema that affected the deserialization of the WorkFlow object?

    string? json = File.ReadAllText(FileDirectory!);
    var opts = new JsonSerializerOptions
    {
        ReadCommentHandling = JsonCommentHandling.Skip
    };
    var rule = JsonSerializer.Deserialize<Workflow>(json, opts);
    
    
    var rules = new List<Workflow> { rule! };
    var re = new RulesEngine.RulesEngine(rules.ToArray());
    
    var input = new RuleParameter("input1", new
    {
        couy = "india",
        loyalityFactor = 2,
        totalPurchasesToDate = 40000,
        totalOrders = 3,
        noOfVisitsPerMonth = 3,
        TotalBilled = 2000
    });
    
    var result = await re.ExecuteActionWorkflowAsync("inputWorkflow", "GiveDiscount20Percent", new List<RuleParameter> { input }.ToArray());
    
    Console.WriteLine(result);
    
  12. RenanCarlosPereira commented on Jul 19, 2024

    @RenanCarlosPereira
    Collaborator

    @RenanCarlosPereira - Thanks for the heads up. That solved that one issue, but now I am getting the following error.

    System.Text.Json.JsonException: 'The JSON value could not be converted to RulesEngine.Models.RuleExpressionType. Path: $.Rules[1].RuleExpressionType | LineNumber: 27 | BytePositionInLine: 46.'

    Was there a change to the schema that affected the deserialization of the WorkFlow object?

    `string? json = File.ReadAllText(FileDirectory!); var opts = new JsonSerializerOptions { ReadCommentHandling = JsonCommentHandling.Skip }; var rule = JsonSerializer.Deserialize(json, opts);

    var rules = new List { rule! }; var re = new RulesEngine.RulesEngine(rules.ToArray());

    var input = new RuleParameter("input1", new { couy = "india", loyalityFactor = 2, totalPurchasesToDate = 40000, totalOrders = 3, noOfVisitsPerMonth = 3, TotalBilled = 2000 });

    var result = await re.ExecuteActionWorkflowAsync("inputWorkflow", "GiveDiscount20Percent", new List { input }.ToArray());

    Console.WriteLine(result); `

    No, we didn't change anything, remember you are Deserializing an workflow not a rule.
    var workflow = JsonSerializer.Deserialize<Workflow>(data, options)!;
    the data in the file is a workflow as it shows in the documentation.
    If you want to Deserialize a rule the file is different

  13. uBoscuBo commented on Jul 19, 2024

    @uBoscuBo

    @RenanCarlosPereira , my apologies. That was a typo. You are correct on that part.

    I'll rephrase the question since I have resolved my issue. According to the previous error,

    System.Text.Json.JsonException: 'The JSON value could not be converted to RulesEngine.Models.RuleExpressionType. Path: $.Rules[1].RuleExpressionType | LineNumber: 27 | BytePositionInLine: 46.'

    The problem was with the second rule's RuleExpressionType. The model itself looks like it has already initialized as a LamdaExpression. The error will be resolved if I remove this line `"RuleExpressionType": "LambdaExpression" from the JSON itself.

    From my observation, explicitly stating the RuleExpressionType can cause issues as it is already initialized within the code. Thoughts? I guess the only problem is that the second rule won't output its expression.

  14. asulwer commented on Jul 19, 2024

    @asulwer
    OwnerAuthor

    @uBoscuBo what are you doing different than the example? the example Deserializes a Workflow, your issue is when you Deserialize a rule directly?

  15. uBoscuBo commented on Jul 19, 2024

    @uBoscuBo

    @asulwer The most significant difference that pops up is using "Actions" in the JSON files, hence why I have to use the ExecuteActionWorkflowAsync command instead of the ExecuteAllRulesAsync.

    For example, from the documentation:

    { "WorkflowName": "inputWorkflow", "Rules": [ { "RuleName": "GiveDiscount20Percent", "Expression": "input1.couy == \"india\" AND input1.loyalityFactor <= 5 AND input1.totalPurchasesToDate >= 20000", "Actions": { "OnSuccess": { "Name": "OutputExpression", //Name of action you want to call "Context": { //This is passed to the action as action context "Expression": "input1.TotalBilled * 0.8" } }, "OnFailure": { // This will execute if the Rule evaluates to failure "Name": "EvaluateRule", "Context": { "WorkflowName": "inputWorkflow", "ruleName": "GiveDiscount10Percent" } } } }, { "RuleName": "GiveDiscount10Percent", "SuccessEvent": "10", "ErrorMessage": "One or more adjust rules failed.", "ErrorType": "Error", "RuleExpressionType": "LambdaExpression", "Expression": "input1.couy == \"india\" AND input1.loyalityFactor <= 2 AND input1.totalPurchasesToDate >= 5000 AND input2.totalOrders > 2 AND input2.noOfVisitsPerMonth > 2", "Actions": { "OnSuccess": { "Name": "OutputExpression", //Name of action you want to call "Context": { //This is passed to the action as action context "Expression": "input1.TotalBilled * 0.9" } } } } ] }

    I guess the only thing I am confused about is why the RuleExpressionType is only needed on the second rule and not the first rule? Is "Workflow" the correct data structure for Action types?

  16. RenanCarlosPereira commented on Jul 19, 2024

    @RenanCarlosPereira
    Collaborator

    Workflows are just a set of rules grouped.
    Actions are executed for each rule inside the workflow.

    you can pass RuleExpressionType or not, as it will fallback to the default both ways works

  17. uBoscuBo commented on Jul 19, 2024

    @uBoscuBo

    @RenanCarlosPereira - Gotcha, that makes sense. I do appreciate y'all patience and assistance.

  18. Repository owner locked and limited conversation to collaborators on Jul 31, 2024
  19. converted this issue into a discussion #61 on Jul 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentation

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions