Skip to content

Arguments

Actions can be given arguments, providing input data to implement the action's logic. Workflow actions support primitive argument types only. Argument's value will be determined at runtime, based on the workflow configuration, and their value can be taken from predefined sources.

Defining arguments

Available arguments for a given workflow action must be declared in the ActionDescriptor. For example:

C#
public class ServiceOrderAssignActionDescriptor : WorkflowActionDescriptor<ServiceOrderAssignActionDescriptor.Handler>
{
    public static readonly string AssignedPositionId = "assignedPositionId";

    public ServiceOrderAssignActionDescriptor()
    {
        this.AddArgument<Guid>(AssignedPositionId);
    }

    public override string Id => "ServiceOrdersActions/ServiceOrderAssignAction";

    public class Handler : IWorkflowActionHandler<ServiceOrder>
    {
        private readonly IReadOnlyRepository<Guid, PositionMetadata> positionRepository;

        public async Task ExecuteAsync(IWorkflowActionHandlerContext<ServiceOrder> context)
        {
            // Get argument's value
            var assignedPositionId = context.GetArgument<Guid>(AssignedPositionId);
            ...
        }
    }
}

The AddArgument requires an argument type and an argument identifier specification. The argument type must be one of the supported types. The argument name must be used to reference this argument later on from the action handler.

Argument type

As said before, argument types supported comprises primitives only. The list of available argument types are:

  • long: which maps to numeric type in the UI
  • string: which maps to text type in the UI
  • Guid: which maps to guid type in the UI
  • bool: which maps to bool type in the UI

Argument binding types

Argument binding defines the source of the argument value, this argument value source could be:

  • From saga instance: the value can be taken from an instance's property
  • From message: the value is taken from the transitioning message, typically prompted for and filled out by user in the UI, when requesting a transition
  • Constant: this is a constant value defined when configuring the workflow

You can define the binding type when configuring the action within the workflow builder, as follows:

```csharp,HL_LINES="12" workflowsModuleOptions.AddWorkflow(WorkflowInfo.DefaultWorkflowTemplateId, builder => { builder.SetInitialState("New", stateBuilder => { stateBuilder .WithTransition("Assign", "Assigned", transitionBuilder => { transitionBuilder.AddAction(actionBuilder => { actionBuilder.WithArguments( ServiceOrderAssignActionDescriptor.AssignedPositionId, binder => binder.FromMessage()); }); }); }); });

Text Only
`binder.FromMessage()` specifies that the argument value must be bound to a
parameter added when triggering workflow transition request.

To bind the argument value to an constant expression, do as follows:

```csharp,HL_LINES="12"
    ...
    actionBuilder.WithArguments<Guid>(
        ServiceOrderAssignActionDescriptor.AssignedPositionId,
        binder => binder.FromConstant(ARGUMENT_VALUE));
    ...

To bind the argument value to a property of the entity, do as follows:

```csharp,HL_LINES="12" ... actionBuilder.WithArguments( ServiceOrderAssignActionDescriptor.AssignedPositionId, binder => binder.FromEntity(entity => entity.ENTITY_PROPERTY)); ...

Text Only
Bear in mind that only properties of the same type of the argument being
configured can be selected.

## Resolving arguments

As we've seen before, argument's values are resolved at runtime, and the value
is obtained from the source defined in the workflow being executed. For example,
given the following workflow fragment of a template:

```csharp,HL_LINES="12"
workflowsModuleOptions.AddWorkflow<ServiceOrder>(WorkflowInfo.DefaultWorkflowTemplateId, builder =>
{
    builder.SetInitialState("New", stateBuilder =>
    {
        stateBuilder
            .WithTransition("Assign", "Assigned", transitionBuilder =>
            {
                transitionBuilder.AddAction<ServiceOrderAssignActionDescriptor>(actionBuilder =>
                {
                    actionBuilder.WithArguments<Guid>(
                        ServiceOrderAssignActionDescriptor.AssignedPositionId,
                        binder => binder.FromMessage());
                });
            });
    });
});

As we've seen before in the example, the action's argument is configured to get its value from the transition message, typically prompting the user for the value. The source of the argument value is called argument binding type.