Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/masastack/MASA.Framework/llms.txt

Use this file to discover all available pages before exploring further.

MASA Framework’s Rules Engine building block externalizes complex business conditions — eligibility checks, pricing tiers, compliance rules — into named rule sets that can be evaluated at runtime without redeploying your service. The default provider is backed by the RulesEngine NuGet package from Microsoft, which accepts rules in a declarative workflow JSON format.

Installation

dotnet add package Masa.Contrib.RulesEngine.MicrosoftRulesEngine
This transitively pulls in Masa.BuildingBlocks.RulesEngine, which contains the core interfaces.

Core Abstractions

IRulesEngineClient

The primary interface you inject into your services. It exposes methods to evaluate rule sets and retrieve results:
MethodReturnsDescription
VerifyAsync(string workflowName, object input)VerifyResponseChecks whether the input passes all rules in the named workflow
ExecuteAsync(string workflowName, object input)ExecuteResponseExecutes the workflow and returns the raw evaluation output
ExecuteActionAsync(string workflowName, object input)ActionResponseExecutes the workflow and returns action results defined in the rule set

Response Types

TypeKey PropertiesUse When
VerifyResponseIsValid, MessageSimple pass/fail decisions — access control, eligibility
ExecuteResponseRule results per rule nameDebugging; when you need per-rule granularity
ActionResponseAction outputsWhen rules trigger side-effect definitions (e.g. set a discount value)

Supporting Types

TypeDescription
IRulesEngineFactoryCreates named IRulesEngineClient instances for multi-engine scenarios
RulesEngineClientBaseBase class for building custom provider implementations
RulesEngineOptionsBuilderFluent builder for rule configuration during registration
RulesEngineRelationOptionsMaps rule workflow names to their backing implementations

Registration

builder.Services.AddRulesEngine(rulesBuilder =>
    rulesBuilder.UseMicrosoftRulesEngine());
The Microsoft Rules Engine provider reads workflow definitions from JSON configuration or in-memory Workflow objects — see microsoft/RulesEngine for the full workflow JSON schema.

Defining Rules

Rules are described in the Microsoft Rules Engine workflow JSON format. A workflow groups one or more rules under a named identifier:
[
  {
    "WorkflowName": "DiscountRules",
    "Rules": [
      {
        "RuleName": "SeniorDiscount",
        "Expression": "input1.Age >= 60"
      },
      {
        "RuleName": "LoyalCustomer",
        "Expression": "input1.TotalOrders >= 10"
      }
    ]
  }
]
Store this file (e.g. rules/discount.json) and load it during startup, or register workflows programmatically through RulesEngineOptionsBuilder.

Usage

Basic Verification

builder.Services.AddRulesEngine(rulesBuilder =>
    rulesBuilder.UseMicrosoftRulesEngine());
public class DiscountService
{
    private readonly IRulesEngineClient _rulesEngine;

    public DiscountService(IRulesEngineClient rulesEngine)
        => _rulesEngine = rulesEngine;

    public async Task<bool> IsEligibleForDiscountAsync(Customer customer)
    {
        var result = await _rulesEngine.VerifyAsync(
            "DiscountRules",
            new { customer.Age, customer.TotalOrders });

        return result.IsValid;
    }
}

Handling the Verification Response

VerifyResponse carries a Message when validation fails, which is useful for returning human-readable feedback:
public async Task<IActionResult> ApplyDiscountAsync(Customer customer)
{
    var result = await _rulesEngine.VerifyAsync(
        "DiscountRules",
        new { customer.Age, customer.TotalOrders });

    if (!result.IsValid)
    {
        return BadRequest(new { error = result.Message });
    }

    // apply discount
    return Ok();
}

Action-Based Rules

When rules include action definitions (e.g. returning a computed discount percentage), use ExecuteActionAsync:
public async Task<decimal> GetDiscountRateAsync(Customer customer)
{
    var response = await _rulesEngine.ExecuteActionAsync(
        "DiscountRateRules",
        new { customer.Age, customer.TotalOrders, customer.Tier });

    // ActionResponse output is a dictionary keyed by rule name
    if (response.Output is decimal rate)
        return rate;

    return 0m;
}

Multiple Rule Engines

Use IRulesEngineFactory when different subsystems require separate engine configurations or rule stores:
public class PricingService
{
    private readonly IRulesEngineClient _pricingEngine;

    public PricingService(IRulesEngineFactory factory)
        => _pricingEngine = factory.Create("PricingEngine");
}
Register named engines through RulesEngineRelationOptions during startup to map engine names to their respective configurations.

Custom Provider

Extend RulesEngineClientBase to integrate a different rule evaluation backend while keeping the same IRulesEngineClient injection contract across your codebase:
public class MyCustomRulesEngineClient : RulesEngineClientBase
{
    protected override Task<VerifyResponse> VerifyCoreAsync(
        string workflowName,
        object input,
        CancellationToken cancellationToken)
    {
        // delegate to your custom engine
    }
}
Register it via RulesEngineOptionsBuilder:
builder.Services.AddRulesEngine(rulesBuilder =>
    rulesBuilder.UseCustomEngine<MyCustomRulesEngineClient>());
Keep rule workflow JSON files in a configuration store (DCC, Azure App Configuration, etc.) rather than embedded in the binary. This lets business analysts update rules without requiring a code deployment.

Build docs developers (and LLMs) love