Start modelling your app today.

Get started for free

What's this?

C# Custom Workflow Logic

Writing custom workflow logic in a C# application.


As with all behaviours, you will occasionally have a need to create custom actions which aren’t available in the standard behaviour. When it comes to Workflow, this will often manifest as a need to trigger actions or results when a workflow state changes. The bots enable you to do this by allowing you to add custom logic into the server-side.

Getting Started

Each entity which has a Workflow behaviour against it (in the Entity Diagram), comes with a protected region where you can work. If you want to add in custom logic to your workflows, this is where you will need to work.

Open the file: \server-side\src\Models\[EntityName].cs, and navigate to the method:

public override void BeforeSave(EntityState operation, [ProjectName]DBContext dbContext, IServiceProvider serviceProvider)

At the end of this method there are two protected regions. We will be using the one titled [Add any custom workflow logic here].

// % protected region % [Add any custom workflow logic here] off begin
// % protected region % [Add any custom workflow logic here] end

Workflow Variables

When using a protected region, it is important to know the context of the region so that you put your code in the correct place. In this scenario, we are changing an entity as it transitions into a new state, so the code will need to be within the BeforeSave method.

The BeforeSave method is called when an entity is being updated, but before the updates are persisted to the database, meaning it is the ideal spot to capture changes to the states.

The newState variable is also useful, as it contains information about the new state which is being transitioned into.

This is where you should be aiming:

var newStates = statesToAdd
  .Where(s => !statesToDelete.Select(d => d.WorkflowStates.Id).Contains(s.Id));

foreach (var newState in newStates)
{
  // % protected region % [Add any custom workflow logic here] off begin
  // % protected region % [Add any custom workflow logic here] end
}

Example Scenario

Lets use an example scenario around the cleaning of our fish tank. This example requires:

  • An Entity named ‘Tank’ with the Workflow behaviour and a date attribute named ‘Last Cleaned’.
  • A workflow named ‘Cleaning Process’ with states ‘Dirty’ and ‘Clean’.
  • The ‘Cleaning Process’ workflow is associated with the ‘Tank’ entity.

When a Tank’s ‘Cleaning Process’ state is changed from ‘Dirty’ to ‘Clean’, we could implement some custom logic to update the last cleaned date, change the status enum, or another custom scenario.

In this example, we will update the Tank’s ‘Last Cleaned’ date to today’s date when it transitions from ‘Dirty’ to ‘Clean’. We will use the newState variable to capture and use this transition.

// % protected region % [Add any custom workflow logic here] on begin
if (newState.WorkflowVersion.WorkflowName == "Cleaning Process" && newState.StepName == "Dirty")
{
    Last Cleaned = DateTime.Now.Date;
}
// % protected region % [Add any custom workflow logic here] end

Make sure you have turned your protected region on!

It is important to check both the name of the workflow and the step name to ensure we don’t accidentally capture a state change with the same name from a different workflow.


Start modelling your app today.