Skip to main content

Introducing Formengine - The New Formbuilder, try for FREE formengine.io.

Workflow API Core

The Core component of the Workflow API manages other components and building the API using an internal builder based on ASP.NET minimal API.

info

The Core component does not implement endpoint functionality, so be sure to include one of the Data components.

Quick Setup

The Core component is included in the base NuGet package OptimaJet.Workflow.Api for .NET 8.0. You can add it to your project with the following command:

dotnet add package OptimaJet.Workflow.Api

The Core component is integrated into an ASP.NET application using three extension methods. The first method adds the necessary services and allows options configuration:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddWorkflowApi(new WorkflowApiOptionsSetup {
SetupCore = options =>
{
// Configure the Workflow Engine API Core options.
options.LicenseKey = "V2-TRIAL-VFJJQUw6MDguMjAuMjAyNTpleUpTWlhOMGNtbGpkR2x2Ym5NaU9uc2lVM1J5YVdOMFEyaGxZMnNpT21aaGJITmxMQ0pOWVhoT2RXMWlaWEpQWmtGamRHbDJhWFJwWlhNaU9qRXdMQ0pOWVhoT2RXMWlaWEpQWmxSeVlXNXphWFJwYjI1eklqb3hNQ3dpVFdGNFRuVnRZbVZ5VDJaRGIyMXRZVzVrY3lJNk5Td2lUV0Y0VG5WdFltVnlUMlpUWTJobGJXVnpJam94TENKTllYaE9kVzFpWlhKUFpsUm9jbVZoWkhNaU9qRXNJa0ZqZEdsMlpVUnBjbVZqZEc5eWVTSTZabUZzYzJVc0lrSnlZVzVrYVc1bklqb2lRbkpoYm1ScGJtY2lMQ0pYYjNKclpteHZkMFZ1WjJsdVpVRndhU0k2SW5SeWRXVWlmU3dpUTNWemRHOXRVbVZ6ZEhKcFkzUnBiMjRpT25SeWRXVjk6bE1iTHBleFplMXk3ZEw5NHVLNm1EZWpkbzVOalZPd1JZZjIvbUZIZmlCb1RiMjdUWFBvQ1gyN1NFeWNiMm1SLzNSckhkWUlWMy9zaG1VWTgvRjZVQk5iQlhMK0lFYmFIYVJ0YVNiVDlldmI1ZWVYaEF4a1RmNmdCVVpiWHBwR3JuY09wNEJIV2dPR2RZZXJSTFNxc0Y3RlRxbGE3Z3RwbkpHTy9IdWJHZWlzPQ==";
},
SetupSecurity = options =>
{
// Configure the Workflow Engine API Security options.
options.DisableSecurity = true;
},
SetupWorkflowRuntime = options =>
{
// Configure the Workflow Engine Runtime options.
options.ConnectionString = "Data Source=:memory:";
}
});
info

This is just a sample. In a real application, the configuration would be stored in an appsettings.json file.

The second method, located in the Data component, adds services with operation implementations based on the data provider you use for your Workflow Engine application. As an example, let's consider using SQLite, but you can choose any other provider. A complete list of providers and integration details can be found in the Data documentation. First, add the appropriate NuGet package:

dotnet add package OptimaJet.Workflow.Api.Sqlite
warning

This version of SQLite may not be compatible with macOS on Apple Silicon processors.

Next, use the extension method to configure the data provider:

builder.Services.AddWorkflowApiSqlite();

The third extension method is applied to your HTTP pipeline, adding the necessary middleware and registering the built API based on the provided settings and connected components:

var app = builder.Build();

app.UseWorkflowApi();

app.Run();

That's it! In just three steps, you've integrated the Workflow API Core.

info

Authentication and authorization settings are handled by the separate Security component, while DisableSecurity is true all API operations will be entirely public.

Multi-Tenant Mode

In Quick Setup we covered how to configure the Workflow API in single-tenant mode. In that mode, the API works with one tenant which identifier is WorkflowApiConstants.SingleTenantId.

For most scenarios this is sufficient to run Workflow Engine, and you don’t need to think about tenants or other multi-tenant details. Single-tenant mode simply hides those details from you.

Configuration

In the Workflow API, a tenant is represented by a tuple of TenantId, WorkflowRuntime, and IWorkflowProvider (a database). A single IWorkflowProvider can serve multiple WorkflowRuntime instances, and each runtime can handle requests from multiple tenants.

Tenants that differ only by TenantId but are served by the same WorkflowRuntime are called logical tenants. Tenants served by different WorkflowRuntime instances are called physical tenants.

To enable multi-tenant mode, use AddWorkflowEngineRuntimeTenants instead of AddWorkflowEngineRuntime. In it, you provide a list of options describing the physical tenants to create. For example:

builder.Services.AddWorkflowEngineRuntimeTenants(
new WorkflowEngineTenantCreationOptions
{
// First physical tenant creation options.
TenantIds = ["MsSqlTenant1", "MsSqlTenant2"],
DataProviderId = PersistenceProviderId.Mssql,
ConnectionString = "Server=localhost,1433;Database=master;User Id=SA;Password=MyPassword;"
},
new WorkflowEngineTenantCreationOptions
{
// Second physical tenant creation options.
TenantIds = ["PostgresTenant1", "PostgresTenant2"],
DataProviderId = PersistenceProviderId.Postgres,
ConnectionString = "Host=localhost;Port=5432;Database=postgres;User Id=postgres;Password=MyPassword;"
}
);

//Don't forget to register the data providers you use.
builder.Services.AddWorkflowApiMssql();
builder.Services.AddWorkflowApiPostgres();

This example defines two physical tenants. The first serves the logical tenants MsSqlTenant1 and MsSqlTenant2 using MS SQL Server data provider, and the second serves PostgresTenant1 and PostgresTenant2 using PostgreSQL.

Key options in WorkflowEngineTenantCreationOptions:

  1. TenantIds — the list of logical tenant identifiers that will be handled by this WorkflowRuntime and IWorkflowProvider (i.e., by this physical tenant).
  2. DataProviderId — the identifier of the data provider used to create the IWorkflowProvider. If omitted, one of the registered providers will be used. The selected provider must be registered as a Data component. Available IDs are listed in PersistenceProviderId.
  3. ConnectionString — the database connection string used to create the IWorkflowProvider. You can define multiple physical tenants that use the same data provider but different connection strings.

The remaining options in WorkflowEngineTenantCreationOptions let you fine-tune how WorkflowRuntime and IWorkflowProvider are created.

Usage

When calling the API in multi-tenant mode, you can explicitly specify TenantId via the WorkflowApiConstants.TenantIdHeader request header ("Workflow-Api-Tenant-ID"). If the header is missing, DefaultTenantId is used, which by default equals WorkflowApiConstants.SingleTenantId.

In multi-tenant mode, it’s recommended to set DefaultTenantId to null. This ensures that every API request must explicitly provide a TenantId; otherwise, the request is rejected with an error.

When a TenantId is provided, the Workflow API resolves the physical tenant that serves the given logical tenant. The request is then processed by the corresponding WorkflowRuntime and IWorkflowProvider.

In an ASP.NET application, you can also access all tenants via the IWorkflowApiTenantRegistry service. If you are in the context of an HTTP request, you can retrieve the current tenant with IWorkflowApiTenantRegistry.GetHttpContextTenant or via an extension method on IServiceProvider.

public class MyController : ControllerBase
{
private readonly IWorkflowApiTenantRegistry _tenantRegistry;

public MyController(IWorkflowApiTenantRegistry tenantRegistry)
{
_tenantRegistry = tenantRegistry;
}

[HttpGet("my-endpoint")]
public IActionResult MyEndpoint()
{
var currentTenant = _tenantRegistry.GetHttpContextTenant(HttpContext);
WorkflowRuntime runtime = currentTenant.Runtime;
// Use currentTenant here...
return Ok();
}
}

Core Options

You can configure the Core component options using the WorkflowApiCoreOptions record provided as ASP.NET IOptions in the service collection. Below is a table describing its properties:

NameTypeDefaultDescription
BasePathstring"workflow-api"The root path to the Workflow Engine API endpoints. If an empty string is specified, endpoints will be accessible via the root path of your application.
LicenseKeystring""The Workflow Engine license key with the Workflow Engine API option enabled. If the key is not provided, the API will not start.
DefaultTenantIdstring?WorkflowApiConstants.SingleTenantIdThe default tenant ID to use when no tenant is specified in the request. If default tenant is null, requests without a tenant specified will be rejected.

Workflow Runtime or Tenant Options

When configuring the Workflow Engine Runtime using AddWorkflowEngineRuntime or AddWorkflowEngineRuntimeTenants, you can specify options for creating WorkflowRuntime instances. These options are defined in the WorkflowEngineRuntimeOptions record. In single-tenant mode, you can provide these options as ASP.NET IOptions in the service collection. Below is a table describing its properties:

NameTypeDefaultDescription
TenantIdsstring[][]The unique tenant identifiers to create with specific runtime options. If no tenant identifiers are specified, the single tenant id WorkflowApiConstants.SingleTenantId will be used.
RuntimeCreationOptionsRuntimeCreationOptionsnew()Options for configuring the Workflow Engine WorkflowRuntime runtime of the tenant.
DataProviderIdstring?nullThe identifier of the data & persistence provider to use for the tenant creation. This identifier is used to select the data provider from the list of registered providers. If not specified, the first found provider or null will be used.
ConnectionStringstring""Specifies the connection string used by the data and persistence provider for tenant creation.
WorkflowApiDataProviderOptionsWorkflowApiDataProviderOptionsnew()Configuration options for the tenant's data provider.
WorkflowProviderCreationOptionsWorkflowProviderCreationOptionsnew()Options for configuring the Workflow Engine IWorkflowProvider persistence provider of the tenant.

Properties of WorkflowApiDataProviderOptions are described in the Data documentation.

Runtime Creation Options

The RuntimeCreationOptions record allows you to configure the WorkflowRuntime instance of a tenant. Below is a table describing its properties:

NameTypeDefaultDescription
RuntimeIdGuidGuid.EmptyThe unique identifier for the Workflow Engine runtime instance.
PersistenceProviderFactoryFunc<IWorkflowProvider?, IPersistenceProvider>provider => provider ?? throw new DataProviderNotFoundException()A factory method for creating an instance of IPersistenceProvider, serving as an interface for storing process data in the Workflow Engine runtime. The parameter provided to the factory is the default IWorkflowProvider provider specified when creating the tenant or null if no provider is specified.
WorkflowBuilderFactoryFunc<IWorkflowProvider?, IWorkflowBuilder>provider => new WorkflowBuilder<XElement>(provider, new XmlWorkflowParser(), provider).WithDefaultCache()A factory method for creating an instance of IWorkflowBuilder, serving as a workflow scheme parser for the Workflow Engine runtime. The parameter provided to the factory is the IWorkflowProvider provider specified when creating the tenant or null if no provider is specified.
ConfigureWorkflowRuntimeAction<WorkflowRuntime> _ => { }A delegate used to configure the Workflow Engine runtime instance. Called after the IPersistenceProvider and IWorkflowBuilder have been registered.
DisableMigrationsExecutionboolfalseIf set to true, disables the execution of WorkflowRuntimeExtensions.RunMigrations(WorkflowRuntime) during the initialization of the WorkflowRuntime.
DisableRuntimeAutoStartboolfalseIf set to true, prevents the WorkflowRuntimeConfigurationExtension.StartAsync() from automatically starting after initialization.
IgnoreNotCompiledGlobalActionsOnStartboolfalseIf set to true, the Workflow Engine runtime will ignore any compilation errors that occur in global actions during its startup.

Workflow Provider Creation Options

The WorkflowProviderCreationOptions record allows you to configure the IWorkflowProvider instance of a tenant. Below is a table describing its properties:

NameTypeDefaultDescription
DisableWritingProcessTransitionHistoryboolfalseIf set to true, prevents the Workflow Engine from saving process transition history to the database.
WriteSubprocessTransitionHistoryToRootProcessboolfalseWhen enabled, writes the transition history of subprocesses directly into the root process transition history.

IWorkflowApiTenantRegistry

Service for managing tenants in a multi-tenant Workflow Engine API setup.

Tenants

Returns

TypeDescription
IReadOnlyCollection<IWorkflowApiTenant>All registered tenants.

Get(string id)

Get a tenant by its id.

Parameters

NameTypeDescription
idstringThe tenant id.

Returns

TypeDescription
IWorkflowApiTenantThe tenant instance.

GetHttpContextTenantId()

Get the tenant id from the current HTTP context based on the provided header or default tenant id.

Returns

TypeDescription
stringThe tenant id.

GetHttpContextTenant()

Get the tenant instance from the current HTTP context.

Returns

TypeDescription
IWorkflowApiTenantThe tenant instance.

GetHttpContextWorkflowRuntime()

Get the workflow runtime instance for the tenant identified in the current HTTP context.

Returns

TypeDescription
WorkflowRuntimeThe workflow runtime instance.

IWorkflowApiTenant

Defines a tenant in a multi-tenant Workflow Engine API setup. In a single-tenant setup registered as a single instance with WorkflowApiConstants.SingleTenantId as its only id.

Ids

Returns

TypeDescription
IReadOnlyCollection<string>All logical tenant ids that map to this tenant instance.

Runtime

Returns

TypeDescription
WorkflowRuntimeThe workflow runtime instance for this tenant.