Skip to content

Workflow transitions

Workflow transitions represent possible paths of the workflow through which it can evolve. A transition is defined from a given workflow state, defines a target workflow state, and finally defines the actions that should be executed as a result of the transition to the new state.

Defining transitions

Transitions are defined using the WorkflowTransitionBuilder instance, available from WorkflowStateBuilder.

C#
workflowsModuleOptions.AddWorkflow<ServiceOrder>(WorkflowInfo.DefaultWorkflowTemplateId, builder =>
{
    builder.SetInitialState("New", stateBuilder =>
    {
        stateBuilder
            .WithTransition("Assign", "Assigned", transitionBuilder =>
            {
                transitionBuilder.AddAction<YOUR_ACTION>(actionBuilder =>
                {
                    // configure transition actions here
                });
            })
            .WithTransition("Acknowledge", "Acknowledged", transitionBuilder =>
            {
                transitionBuilder.AddAction<ServiceOrderAcknowledgeActionDescriptor>(actionBuilder =>
                {
                    // configure transition actions here
                });
            })
            ...
    });
}

Conditional transitions

To constraint certain actions based on the workflow state, you could specify by means of GraphQL expression, when a given transition could be considered available. Available transitions are shown in the workflow UI, whereas transitions that don't match the condition won't be shown.

To specify a condition for a transition, you have to use the WithCondition method available in the WorkflowTransitionBuilder.

C#
workflowsModuleOptions.AddWorkflow<ServiceOrder>(WorkflowInfo.DefaultWorkflowTemplateId, builder =>
{
    builder.SetInitialState("New", stateBuilder =>
    {
        stateBuilder
            .WithTransition("Assign", "Assigned", transitionBuilder =>
            {
                transitionBuilder.WithCondition("{ YOUR_GQL_CONDITION }");
                transitionBuilder.AddAction<YOUR_ACTION>(actionBuilder =>
                {
                    // configure transition actions here
                });
            })
            .WithTransition("Acknowledge", "Acknowledged", transitionBuilder =>
            {
                transitionBuilder.AddAction<ServiceOrderAcknowledgeActionDescriptor>(actionBuilder =>
                {
                    // configure transition actions here
                });
            })
            ...
    });
}

The transition condition must be a valid GraphQL expression and it can involve any of the entity instance properties, including those accessible through navigation (relationship whit other instances).

Important

If the GraphQL condition involves accessing any of the entity's relationships,

you will have to includes those relations through IncludeSpecifications, this is important when using saga's state machines entities.

Target state

Target state of the transition can be assigned one or more actions. These actions will be executed as a result of the workflow entering the state, when the transition operation completes.

Note

Workflow state actions are executed after transition actions do.

Target state of a transition is defined when declaring the transition using WithTransition method of WorkflowStateBuilder instance. This is the simplest way to configure the target state, such as in the following example:

```csharp, HL_LINES="6" workflowsModuleOptions.AddWorkflow(WorkflowInfo.DefaultWorkflowTemplateId, builder => { builder.SetInitialState("New", stateBuilder => { stateBuilder .WithTransition("Assign", "Assigned", transitionBuilder => { transitionBuilder.WithCondition("{ YOUR_GQL_CONDITION }"); transitionBuilder.AddAction(actionBuilder => { // configure transition actions here }); }) ... }); }

Text Only
From the previous example, the `Assigned` target state is configured as a
resulting state for the transition called "Assign".

However, sometimes you need to particularize the target state behavior, to add
actions for instance. To do so you'll need to leverage the
`WorkflowTargetStateBuilder` features, available through `WithTargetState`
method, as you can see here below:

```csharp, HL_LINES="8"
workflowsModuleOptions.AddWorkflow<ServiceOrder>(WorkflowInfo.DefaultWorkflowTemplateId, builder =>
{
    builder.SetInitialState("New", stateBuilder =>
    {
        stateBuilder
            .WithTransition("Assign", transitionBuilder =>
            {
                transitionBuilder.WithTargetState(
                    "Assigned",
                    targetStateBuilder => {
                        targetStateBuilder.AddAction<YOUR_STATE_ACTION>(
                            actionBuilder =>
                            {
                                // configure state actions here
                            });
                    });
                transitionBuilder.WithCondition("{ YOUR_GQL_CONDITION }");
                transitionBuilder.AddAction<YOUR_TRANSITION_ACTION>(
                    actionBuilder =>
                    {
                        // configure transition actions here
                    });
            })
            ...
    });
}

WithTargetState, from the previous example, shows us how to define and deeper configure a target state for from within a transition definition.

Important

There must be at least a target state defined for a transition, otherwise the workflow

builder will fail to complete the building process.

Conditional target states

A transition can define multiple conditional target states, which will be selected based on the conditions specified for them. Let's see the following example:

```csharp, HL_LINES="8" workflowsModuleOptions.AddWorkflow(WorkflowInfo.DefaultWorkflowTemplateId, builder => { builder.SetInitialState("New", stateBuilder => { stateBuilder .WithTransition("Assign", transitionBuilder => { transitionBuilder.WithTargetState( "Assigned", "{ YOUR_STATE_CONDITION }", targetStateBuilder => { targetStateBuilder.AddAction( actionBuilder => { // configure state actions here }); });

Text Only
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
            transitionBuilder.WithTargetState(
                "OtherState",
                "{ YOUR_STATE_CONDITION }",
                targetStateBuilder => {
                    targetStateBuilder.AddAction<YOUR_STATE_ACTION>(
                        actionBuilder =>
                        {
                            // configure state actions here
                        });
                });

            transitionBuilder.WithCondition("'{ YOUR_GQL_CONDITION }`");
            transitionBuilder.AddAction<YOUR_TRANSITION_ACTION>(
                actionBuilder =>
                {
                    // configure transition actions here
                });
        })
        ...
});

} ```

You may want to specify multiple candidate target states, each of them with their corresponding condition, constraining entering that state. The transition condition is expressed through GraphQL expressions, which will be executed against the saga instance. All entity instance properties and their relationships are available to express the state conditions. Be aware of using the corresponding IncludeSpecifications to get hydrated the entity's relationship for the expression to evaluate the expression properly.

Important

If there is only one target state defined for a given transition, its condition

will never be evaluated, and the state will be consider valid despite of the condition specified.

Important

Conditional state are evaluated according to the order in which they were defined.

As of now, the first matching state wins and the workflow will move on to that target state when completes the transition operation.