Flexbase
  • Flexbase
  • Introduction
  • #JoyofCoding with Flexbase
  • Core Concepts
    • Flexbase
    • Flexstudio
      • Commands & Events
  • Thinking in Flexbase
    • Features and Modules
    • Designing APIs using Flexbase Control Flow
  • Sample Application
  • Solution Structure
    • Getting Started
      • Application
        • Introduction to Solution
        • Demo - Solution Generation
        • Solution Structure Overview
        • Architecture Overview
        • Clean architecture layer
        • Common Configurations
      • Features
        • Understanding Feature
        • Use Case
        • First Feature - Add Customer
        • Second Feature - Update Customer
        • Third Feature - Delete Customer
        • Query Features
  • Input Output Models
  • Messages
  • Domain
  • Pre Bus
  • Post Bus
  • Subscribers
  • Bus Gamma
  • Persistence
  • Hosting
  • Startup Code - WebAPI
  • Startup Code - Background Job
  • Endpoint - AppSettings
  • Bridge
  • Basic CRUD - Insert & Update
  • Introduction
  • View Generated API Definition in Swagger
  • Walkthrough Generated Code Insert
  • Walkthrough Generated Code Query GetById
  • Domain Model
  • Migration
  • AppSettings
  • Bus : How Basic Routing Config Works
  • INSERT : Input API Model
  • INSERT : Attribute Validation
  • INSERT : Plugin Validation
  • INSERT : Mapper
  • INSERT : Controller
  • INSERT : Services
  • INSERT : PostBus Handler
  • INSERT : PostBus Subscriber
  • INSERT : Demo In Action
  • QUERY : Output API Model
  • QUERY : Build and Fetch Pattern
  • QUERY : Demo In Action
  • Basic CRUD 2
    • Introduction
    • View Generated API Definition In Swagger
  • Walkthrough Generated Code Update
  • Walkthrough Generated Code Delete
  • Walkthrough Generated Code GetList
  • Walkthrough Generated Code Get Paged List
  • Update In Action
  • Delete In Action
  • GetList In Action
  • GetPagedList In Action
  • Konarch
Powered by GitBook
On this page

INSERT : Services

BasicCRUD Insert Query with Bridge

PreviousINSERT : ControllerNextINSERT : PostBus Handler

Last updated 4 years ago

Now let us look at the services layer. ProcessServices is present in PreBus.

    public partial interface IProcessCustomerService
    {
        /// <summary>
        /// YourRemarksForMethod
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        Task<CommandResult> AddCustomer(AddCustomerParams @param);
    }

    /// <summary>
    /// 
    /// </summary>
    public class AddCustomerParams : ProcessServiceInputParameterBridge
    {
        public AddCustomerInputAPIModel Model { get; set; }
    }
public partial class ProcessCustomerService : IProcessCustomerService
    {
        
        /// <summary>
        /// YourRemarksForMethod
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<CommandResult> AddCustomer(AddCustomerParams param)
        {
            AddCustomerDataPacket packet = _flexHost.GetFlexiFlowDataPacket<AddCustomerDataPacket>();
            packet.InputParams = param;

            try
            {
                FlexiBusinessRuleSequenceBase<AddCustomerDataPacket> sequence = _flexHost.GetFlexiBusinessRuleSequence<AddCustomerSequence, AddCustomerDataPacket>();

                await FlexiBusinessRule.Run(sequence, packet);
            }
            catch (FlexiFlowAbnormalTerminationException ex)
            {
                packet.AddError("requesterror", ex);
                return new CommandResult(Status.Failed, packet.Errors());
            }

            if (packet.HasError)
            {
                return new CommandResult(Status.Failed, packet.Errors());
            }
            else
            {
                AddCustomerCommand cmd = new AddCustomerCommand
                {
                    Id = _pkGenerator.GenerateKey(),
                    model = param.Model,
                    HostContextInfo=param.HostContextInfo

                };

                await ProcessCommand(cmd);

                CommandResult cmdResult = new CommandResult(Status.Success);
                AddCustomerResultModel outputResult = new AddCustomerResultModel();
                outputResult.Id = cmd.Id;
                cmdResult.result = outputResult;
                return cmdResult;
            }
        }
    }
    public class AddCustomerResultModel : FlexOutputAPIModelForCreate
    {
    }

Now let us look at the IProcessCustomerService and ProcessCustomerService, here we have the IProcessCustomerService_AddCustomer where we have AddCustomerParams, which is in turn derived from the ProcessServiceInputParameterBridge which contains the HostContextInfo, which enables you to pass the host info from the controller as we saw earlier. In AddCustomer, it takes the data packet that carries the input received from the form throughout the plugins using this data packet. It creates a FlexiSequence which contains the Plugins and then BusinessRule will execute the sequence.

public class AddCustomerSequence : FlexiBusinessRuleSequenceBase<AddCustomerDataPacket>
    {
        /// <summary>
        /// 
        /// </summary>
        public AddCustomerSequence()
        {
            this.Add<IsUnique>(); this.Add<DoesNotStartWithNumber>();
        }
    }

Whenever you are generating your code the FlexiSequence will be always overwritten and all the plugins mentioned in the feature diagram automatically it will get configured in the generated code. You have to just write the logic of your validations in the plugins. The plugins will never be over written in any of the code generation, so the code that you have already written remains safe.

if (packet.HasError)
            {
                return new CommandResult(Status.Failed, packet.Errors());
            }
            else
            {
                AddCustomerCommand cmd = new AddCustomerCommand
                {
                    Id = _pkGenerator.GenerateKey(),
                    model = param.Model,
                    HostContextInfo=param.HostContextInfo

                };

                await ProcessCommand(cmd);

                CommandResult cmdResult = new CommandResult(Status.Success);
                AddCustomerResultModel outputResult = new AddCustomerResultModel();
                outputResult.Id = cmd.Id;
                cmdResult.result = outputResult;
                return cmdResult;
            }

If the packet is filled with any error in any of the plugin validations during the business rule validation, it will return to the controller and then controller will return the messages back to the user giving the details of the errors. If everything is validated without any errors, a command created and the primary key is generated and passed along with the command for further processing. default PK generator will generate a Sequential GUID for you. You can replace the logic and configure it with the DI provider in the startup code.

public partial class ProcessCustomerService : IProcessCustomerService
    {
        private async Task ProcessCommand(AddCustomerCommand cmd)
        {
            await _bus.Send(cmd);

        }

    }

So by default, the services will follow have eventual consistency processing. So here bus.send will be called to send the message in the bus. It will send the command in the bus which will be received by the Handler end point, we saw that how the Handler end point mapping is happening and how it will identify the Handler in our earlier videos. There is another option for non-eventual consistency. In non-eventual consistency mode (it can be configured during code generation), the message is not sent into the bus and the execution happens in the same web api end point process.

If the transaction is not like a very critical transaction like a money withdraw transaction in banking and update the amount immediately, you can prefer the eventual consistency using Bus, so that your scaling can happen with ease as you grow your business. In real life scenario, you can handle most of the transactions in an eventual consistency mode. Amazon uses this pattern in most of its operations.