Skip to main content.

Site Map

Site Map

Business Rules

A microservice should allow easy customization of its logic for development speed and maintainability.

We have create a unique, generic business rule engine that allows unprecedented customization of logic for a microservice. Business rules allow you to "hook" into the API request pipeline of any microservice already built and customize it however you like.

Business rules are registered with the system and can even be changed dynamically. A business rule can perform validations, logic, pre/post behaviors, publishing events, integrations, or just about anything you can code. Broadcasts, Events, Models and Processes are all used with the business rule engine. Simply changed the type that the rule is registred with.

Business Rule Engine

The Business Rule Engine is broken down into two main pieces. The IBusinessRuleRegistry interface is used to register and manipulate Business Rules, typically done during the RegisterBrick() extension method. The IBusinessRuleService interface is responsible for processing Business Rules.

Multiple business rules can be added to any type. Business Rules define a Priority property that allow ordered execution for expected results. You can add, replace and remove any business rule you want as it is serviced by a ConcurrentDictionary.

The BusinessRuleContext class is responsible for hold a reference to the object that is being processed against. It is passed to each business rule as each on is evaluated. It also provides a state dictionary so that you can pass data in-between business rules.

Defining a Business Rule

The following example defines a generic business rule. This rule is developed so that for any registered domain objects, after it is created, it will serialize the object to an information log message. The RegisterRule method is called during startup during the RegisterBrick() extension method to register the Business Rule. The ExecuteRuleAsync method performs the execution logic of the rule.


public partial class CreateLogRule<TDomainObject> : BusinessRule
        where TDomainObject : IDomainObject<TDomainObject>
    {        
        protected readonly ILogger _logger;

        public CreateLogRule(ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger<CreateLogRule<TDomainObject>>();
            Priority = PRIORITY_NORMAL;
        }

        public static void RegisterRule(IBusinessRuleRegistry registry)
        {
            registry.RegisterItem(
                typeof(DomainCreateAfterEvent<TDomainObject>), // Change this for models/events/broadcasts/processes
                typeof(CreateLogRule<TDomainObject>));
        }

        public override Task<IResponse> ExecuteRuleAsync(IBusinessRuleContext context)
        {            
            if (context.Object is DomainCreateAfterEvent<TDomainObject> context)
                _logger.LogInformation(JsonConvert.SerializeObject(context.DomainObject));                

            return Task.FromResult<IResponse>(new Response());
        }
    }

This business rule is registered during the RegisterBrick() extension method as follows:


    //Register Business rules
    var registry = serviceScope.ServiceProvider.GetRequiredService<IBusinessRuleRegistry>();
    CreateLogRule<MyDomainObject>.RegisterRule(registry);

Defining a Business Rule for Domain Object Validation

Before every create or update method is invoked on a domain object, it first must pass validation. If using model-based attributes, these would be handled prior to your methods invocation in the request pipeline. The Business Rule engine defines for validations after the method is invoked.


public partial class ValidateRuleMyDomainObject : BusinessRule        
    {        
        protected readonly ILogger _logger;

        public ValidateRuleMyDomainObject(ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger<ValidateRuleMyDomainObject>();
            Priority = PRIORITY_NORMAL;
        }

        public static void RegisterRule(IBusinessRuleRegistry registry)
        {
            registry.RegisterItem(
                typeof(MyDomainObject), // Change this for models/events/broadcasts/processes
                typeof(ValidateRuleMyDomainObject));
        }

        public override Task<IResponse> ExecuteRuleAsync(IBusinessRuleContext context)
        {            
            var response = new Response();

            if (context.Object is MyDomainObject myobj)
            {
                if(string.IsNullOrEmpty(myobj.Name))
                {
                    response.AddMessage(ResponseMessage.CreateError("Name is invalid"));
                    return Task.FromResult<IResponse>(response);
                }
            }                

            return Task.FromResult<IResponse>(response);
        }
    }

This business rule is registered during the RegisterBrick() extension method as follows:


    //Register Business rules
    var registry = appbuilder.ServiceProvider.GetRequiredService<IBusinessRuleRegistry>();
    ValidateRuleMyDomainObject.RegisterRule(registry);

Executing Business Rules

Processing of Business Rules is done by accessing the IBusinessRuleService interface via dependency injection. The following example shows how to invoke the validation rule defined above.


    public async Task MyExampleDependencyInjection(IBusinessRuleService businessRuleService)
    {
        var domainObject = new MyDomainObject();
        BusinessRuleContext context = new BusinessRuleContext(domainObject);
        var response = await businessRuleService.ExecuteDomainRulesAsync(context);
    }