Workflow Core Getting Started

Zaki Mohammed Zaki Mohammed
April 03, 2022 | 4 min read | 151 Views

One has to follow some process or a workflow to bring down some mighty and complex tasks, that require actions on each step and need to be fault-tolerant at the same time. Say hello to one such cool, lightweight, and fault-tolerant workflow engine built for .NET to deal with most of the workflow kinda requirements without putting you in stress and discomfort. In this article, we will be getting started with the Workflow Core engine, along with the friendly neighborhood .NET Core (6.0).

Carrying out operations one after the other as a workflow requires some checkpoints, roll-back options, tracking of steps, and announcing completion once everything appears to be okay to commit the changes. All of this seems okay if you are already a ninja/samurai developer, but also you can understand such requirements are there and common for most kinds of projects, and recoding the same logic again and again doesn't seem to be thoughtful. Situation suitable for Workflow Core engine; if you are speaking the same C# language.

As a human being, I am listing some of the few reasons why you can consider Workflow Core. Following features supported by Workflow Core:

  1. Handle long running process
  2. Split/Join processes
  3. Persistent steps
  4. Retry and resume options
  5. JSON/YAML definition
  6. Error handing

The only thing Workflow Core is failing to provide some kind of visual representation of the flow which is created. Although not required from a developer/engineer perspective but surely add value for business bodies (like Business Analyst, Architects, etc.). Let us jump into coding.

.NET Core SDK Requirements

Before we even begin, let me clarify the requirement to use Workflow Core with .NET Core. In this article, we are specifically considering .NET Core and not .NET Standard. For .NET Core, Workflow Core requires .NET Core 2.0 SDK to be installed on your machine. Checkout which versions of SDK are already installed on your machine by running the following command:

dotnet --list-sdks
2.1.202 [C:\Program Files\dotnet\sdk]
6.0.201 [C:\Program Files\dotnet\sdk]

I have installed the above 2 versions of .NET Core SDK on my machine. If you do not have 2.0; then try to install from .NET Core official website.

Initialize Project and Dependencies

Run the following command to create a project from scratch and try to run the most complex code for mankind (the "Hello World").

dotnet new console -o workflow-start
dotnet run

Install following Nuget pacakges through .NET Core CLI:

dotnet add package WorkflowCore
dotnet add package Microsoft.Extensions.DependencyInjection
dotnet add package Microsoft.Extensions.DependencyInjection.Abstractions
dotnet add package Microsoft.Extensions.Logging

Starting with Workflow Core

For any workflow creation as per Workflow Core documentation, you have to follow below shown steps:

  1. Create Steps
  2. Create Workflow
  3. Register and start the Workflow from the main program file

Make sure you follow the above order, it will provide you focus and ease in creating workflow in proper manner. Follow the below folder structure to manage your workflows without any hassle:

workflow-start
|-- Workflows
    |-- ProcessPayment
        |-- Steps
            |-- ApplyDiscount.cs
            |-- ApplyShipping.cs
            |-- Finalize.cs
            |-- Initialize.cs
        |-- ProcessPaymentWorkflow.cs
|-- GlobalUsings.cs
|-- Program.cs
|-- workflow-start.csproj

In the GlobalUsings file we are just adding the Workflow Core required packages as global using.

GlobalUsings.cs

global using Microsoft.Extensions.DependencyInjection;
global using WorkflowCore.Interface;
global using WorkflowCore.Models;

1. Create Steps

Below is the first step which is initializes the process payment flow (nothing fancy right now, just printing Initialize on the console).

Workflows/ProcessPayment/Steps/Initialize.cs

public class Initialize : StepBody
{
    public override ExecutionResult Run(IStepExecutionContext context)
    {
        Console.WriteLine("Initialize");
        return ExecutionResult.Next();
    }
}

Likewise, we will create remaining steps: Apply Discount, Apply Shipping, and Finalize.

2. Create Workflow

Create the workflow ProcessPaymentWorkflow which will contain the workflow code logic between these steps:

Workflows/ProcessPayment/ProcessPaymentWorkflow.cs

public class ProcessPaymentWorkflow : IWorkflow
{
    public string Id => "ProcessPaymentWorkflow";

    public int Version => 1;

    public void Build(IWorkflowBuilder<object> builder)
    {
        builder
            .UseDefaultErrorBehavior(WorkflowErrorHandling.Suspend)
            .StartWith<Initialize>()
            .Then<ApplyDiscount>()
            .Then<ApplyShipping>()
            .Then<Finalize>();
    }
}

By using simple StartWith and Then methods we can create a sequence of steps.

3. Register and start the Workflow

Finally, we will register our workflow to the host and start the Process Payment workflow as shown below:

Program.cs

var serviceProvider = new ServiceCollection()
    .AddLogging()
    .AddWorkflow()
    .BuildServiceProvider();

var host = serviceProvider.GetService<IWorkflowHost>();
if (host == null)
    throw new Exception("Host not initialized");

host.RegisterWorkflow<ProcessPaymentWorkflow>();

host.Start();

host.StartWorkflow("ProcessPaymentWorkflow");

Console.ReadLine();
host.Stop();

Here, we are registering the ProcessPaymentWorkflow by calling the register method of host object:

host.RegisterWorkflow<ProcessPaymentWorkflow>();

Then starting the workflow using start method of the host objcet:

host.StartWorkflow("ProcessPaymentWorkflow");

Now, when you run the project it will simply print these steps console text on you console window:

dotnet run
Initialize
ApplyDiscount
ApplyShipping
Finalize

We will continue to explore some of the other Workflow Core features in upcoming posts. Stay tuned!


Zaki Mohammed
Zaki Mohammed
Learner, developer, coder and an exceptional omelet lover. Knows how to flip arrays or omelet or arrays of omelet.