Sample workflow system with ASP.NET Core, Angular and microwf explained - the refactoring

This blog post is a follow up of my last article where I wrote about the intention to refactor the Namespace tomware.Microwf.Engine to its own project. Well I did! It is even available as a nuget package.

It comes along with persisting the workflow instances as well as their workflow variables. There is also the option to run a background service which acts as a job queue in order to process workflow steps that require no user interaction.

In order to use it in your ASP.NET Core project you need to do the following two steps:

  • registering services
  • inheriting from EngineDbContext

You can all look it up in the samples project if you are still familiarizing yourself with the setup of a ASP.NET Core project.

Registering services

In the Startup.cs class you need to register the services by calling the AddWorkflowEngineServices extension method.

var workflowConf = CreateWorkflowConfiguration();
IOptions<ProcessorConfiguration> processorConf = GetProcessorConfiguration(services);

  .AddWorkflowEngineServices<DomainContext>(workflowConf, processorConf.Value)

In the above snippet you see that you need to tell the extension method the type of your DomainContext class as well as pass in an instance of a WorkflowConfiguration and a ProcessorConfiguration.

The WorkflowConfiguration tells the library what workflows within the system exist. You can configure it either by creating such an object within code or by leveraging the IOptions<T> interface and configure it within your appsettings (see the following snippet).

"Workflows": {
  "Types": [
      "Type": "HolidayApprovalWorkflow",
      "Title": "Holiday",
      "Description": "Simple holiday approval process.",
      "Route": "holiday"
      "Type": "IssueTrackingWorkflow",
      "Title": "Issue",
      "Description": "Simple issue tracking process.",
      "Route": "issue"

The ProcessorConfiguration follows the same principles as the WorkflowConfiguration.

"Worker": {
  "Enabled": false,
  "Intervall": 5000

If you make use of the “Worker” you might also call the second extension method SubscribeMessageHandlers within the Configure method that subscribes the message handlers. This is required in order to receive WorkItem messages and add it to the “Worker’s” queue.


Just publish a WorkItem via the IMessageBus interface.

WorkItem wi = WorkItem.Create(IssueTrackingWorkflow.ASSIGN_TRIGGER, issue.Id, issue.Type);
await _messageBus.PublishAsync(wi);

That’s it basically. In case I missed something just go and have a look on the samples Startup.cs class.

Inheriting from EngineDbContext

Because we want to have EF Core to persist our workflows we need to inherit the applications DbContext from EngineDbContext (see sample snippet below). This will ensure that during “dotnet ef” commands all the required tables gets created.

public class DomainContext : EngineDbContext
  public DomainContext(DbContextOptions<DomainContext> options) : base(options) { }

  public DbSet<Issue> Issues { get; set; }
  public DbSet<Holiday> Holidays { get; set; }


That’s it! The best part in my opinion is that the package targets the netstandard2.0. This means it should run almost everywhere.

Now I have some more requirements I would like to have such as having a history for a workflow instance. This is a quite common requirement when having a workflow engine.

I also would like to improve my personal css skills and therefore I decided to rewrite the Angular client without depending on the popular Bootstrap framework. I am doing it all by myself ;-).

Cheers Thomas