Skip to Content
Evaluate Get Started Plugins Glossary

Managing Parameters

Control workflow execution by storing, modifying, and branching on process parameter values. Without SetParameter, RemoveParameter, and CheckParameter, every scheme that needs to remember a decision, store intermediate data, or route based on dynamic conditions would require custom actions or conditions defined in the scheme. These built-in actions and conditions handle the full lifecycle of process parameters.

Real-world scenario: product delivery routing

An e-commerce order workflow assigns each order a product type - "Digital" (software, e-books) or "Physical" (hardware, shipped goods). The product type is set in the first activity using a C# expression that randomly picks one of the two values. A Decide activity then routes the order to the correct delivery branch:

  • If the product type is "Digital", the order goes to DigitalDelivery.
  • For any other value (fallback handled by the Otherwise condition), the order goes to PhysicalDelivery.

This demonstrates how parameters control process routing. In production, the product type would come from an external system or user input rather than a random expression.

Workflow scheme

The three SetParameter calls in the Start activity generate order data. The process then passes through Decide, which auto-evaluates the conditions on its outgoing transitions.

Manage parameters workflow scheme

Related capabilities: SetParameter action, RemoveParameter action, CheckParameter condition, Otherwise condition type.

manage-parameters.xml
<Process Name="ManageParametersExample" CanBeInlined="false">  <Designer />  <Commands>    <Command Name="Continue" />  </Commands>  <Activities>    <Activity Name="Start" State="Start" IsInitial="True"              IsFinal="False" IsForSetState="True"              IsAutoSchemeUpdate="True">      <Implementation>        <ActionRef Order="1" NameRef="SetParameter">          <ActionParameter><![CDATA[            {              "ParameterName": "OrderId",              "Value": "Guid.NewGuid().ToString()"            }          ]]></ActionParameter>        </ActionRef>        <ActionRef Order="2" NameRef="SetParameter">          <ActionParameter><![CDATA[            {              "ParameterName": "Amount",              "Value": "100.00"            }          ]]></ActionParameter>        </ActionRef>        <ActionRef Order="3" NameRef="SetParameter">          <ActionParameter><![CDATA[            {              "ParameterName": "ProductType",              "Value": "Guid.NewGuid().ToByteArray()[0] < 128 ? \"Digital\" : \"Physical\""            }          ]]></ActionParameter>        </ActionRef>      </Implementation>      <Designer X="100" Y="210" />    </Activity>    <Activity Name="Decide" State="Decide"              IsInitial="False" IsFinal="False"              IsForSetState="True"              IsAutoSchemeUpdate="True">      <Designer X="520" Y="210" />    </Activity>    <Activity Name="DigitalDelivery" State="DigitalDelivery"              IsInitial="False" IsFinal="True"              IsForSetState="True"              IsAutoSchemeUpdate="True">      <Designer X="940" Y="130" />    </Activity>    <Activity Name="PhysicalDelivery" State="PhysicalDelivery"              IsInitial="False" IsFinal="True"              IsForSetState="True"              IsAutoSchemeUpdate="True">      <Designer X="940" Y="290" />    </Activity>  </Activities>  <Transitions>    <Transition Name="Start_Decide"                To="Decide" From="Start"                Classifier="Direct" IsFork="false"                MergeViaSetState="false"                DisableParentStateControl="false">      <Triggers>        <Trigger Type="Command" NameRef="Continue" />      </Triggers>      <Conditions>        <Condition Type="Always" />      </Conditions>      <Designer />    </Transition>    <Transition Name="Decide_DigitalDelivery"                To="DigitalDelivery" From="Decide"                Classifier="Direct" IsFork="false"                MergeViaSetState="false"                DisableParentStateControl="false">      <Triggers>        <Trigger Type="Auto" />      </Triggers>      <Conditions>        <Condition Type="Action" NameRef="CheckParameter"                   ConditionInversion="false">          <ActionParameter><![CDATA[            {              "ParameterName": "ProductType",              "CompareType": "Contains",              "Value": "Digital"            }          ]]></ActionParameter>        </Condition>      </Conditions>      <Designer />    </Transition>    <Transition Name="Decide_PhysicalDelivery"                To="PhysicalDelivery" From="Decide"                Classifier="Direct" IsFork="false"                MergeViaSetState="false"                DisableParentStateControl="false">      <Triggers>        <Trigger Type="Auto" />      </Triggers>      <Conditions>        <Condition Type="Otherwise" />      </Conditions>      <Designer />    </Transition>  </Transitions></Process>

How the scheme works

Once the scheme is saved and the BasicPlugin is registered with the WorkflowRuntime, the process runs as follows:

// 1. Create an instance from the schemevar processId = Guid.NewGuid();var createParams = new CreateInstanceParams("ManageParametersExample", processId);await runtime.CreateInstanceAsync(createParams);// -> Start executes SetParameter x 3://    OrderId = "b1a2c3d4-..." (GUID)//    Amount = 100.00//    ProductType = "Digital" or "Physical" (selected from a random GUID byte)// 2. Execute the Continue commandvar commands = await runtime.GetAvailableCommandsAsync(processId, identityId: null);var command = commands.First(c => c.CommandName == "Continue");await runtime.ExecuteCommandAsync(command, identityId: null, impersonatedIdentityId: null);// -> Process moves from Start to Decide// 3. Decide auto-evaluates its outgoing transitions//    If ProductType contains "Digital" -> DigitalDelivery (Finalized)//    Otherwise                         -> PhysicalDelivery (Finalized)// 4. Check the final statusvar status = await runtime.GetProcessStatusAsync(processId);// -> ProcessStatus.Finalized

The Auto trigger on both transitions from Decide means the process evaluates CheckParameter immediately upon entering Decide. The condition uses Contains to check whether ProductType contains "Digital". If it does, the process takes that branch. Otherwise, the Otherwise condition catches the fallback. No additional command is needed.

Reference

BasicPlugin provides the following actions and conditions for managing process parameters.

SetParameter action

Stores a value in a process parameter. The value is interpreted as a C# expression by default.

ParameterRequiredDefaultDescription
ParameterNameYes-Name of the parameter to set.
ValueYes-Value to store. With expression compilation enabled (the default), provide a non-empty C# expression. For string literals, escape quotes: \"value\". To store an empty string, use the explicit C# string literal \"\" in the action JSON. For expressions, use code such as Guid.NewGuid().ToString().
ForRootProcessYesfalseWhen true, operates on the root process parameter in a subprocess hierarchy.

RemoveParameter action

Deletes a process parameter by name.

ParameterRequiredDefaultDescription
ParameterNameYes-Name of the parameter to remove.
ForRootProcessYesfalseWhen true, operates on the root process parameter in a subprocess hierarchy.

CheckParameter condition

Compares a parameter value against a reference value. Returns true when the comparison matches.

ParameterRequiredDefaultDescription
ParameterNameYes-Name of the parameter to check.
CompareTypeYesEqualComparison operator. See CompareType enum.
ValueNoEmpty stringValue to compare against. For In/NotIn, use a delimited list.
SeparatorYes,Delimiter for In/NotIn comparison.
ForRootProcessYesfalseWhen true, reads the parameter from the root process.

Enums

BasicPlugin uses the following enums in action parameters.

CompareType

The CompareType parameter in CheckParameter determines how the parameter value is compared.

ValueExample
Equaln == v
NotEqualn != v
Contains"yummy" contains "umm"
StartWith"yummy" starts with "yu"
EndWith"yummy" ends with "my"
NotContains"yummy" does not contain "yy"
StartAndEndWith"yummy" starts and ends with "y"
NotStartWith"yummy" does not start with "my"
NotEndWith"yummy" does not end with "yu"
NotStartAndEndWith"yummy" does not start or end with "mm"
Greatern > v
Lessn < v
GreaterOrEqualn >= v
LessOrEqualn <= v
In5 in (1, 2, 3, 4, 5)
NotIn6 not in (1, 2, 3, 4, 5)

Troubleshooting common errors

Common mistakes when working with parameter actions and conditions.

Common mistakes

  • String values without expression escaping: When using SetParameter.Value with a static string, wrap it in escaped C# quotes: "value". Without them, the expression compiler treats the value as a variable name and throws (1,28): error CS0103: The name 'X' does not exist in the current context. Fix: escape as \"X\".
  • Using Name instead of NameRef: Condition Type="Action" requires NameRef, not Name. Using Name causes the Designer to show an empty action field.

See also

Frequently asked questions

How do I pass a plain string to SetParameter without the expression compiler breaking it?

Wrap the value in escaped C# quotes inside the JSON: "Value":"\"hello\"". The JSON parser unescapes this to the C# string literal "hello", which the expression compiler compiles as a plain string. Without the quotes, the compiler tries to find a variable named hello and throws CS0103.

How do I pass a GUID or other dynamic value to SetParameter?

Use any C# expression as the value: "Value":"Guid.NewGuid().ToString()" generates a new GUID. A ternary expression based on a random GUID byte, "Value":"Guid.NewGuid().ToByteArray()[0] < 128 ? \"Digital\" : \"Physical\"", selects one of two string values. The expression compiler evaluates the value as C# code.

How do I delete a parameter?

Add the RemoveParameter action to an activity with ParameterName set to the parameter name. Set ForRootProcess to true to delete from the root process in a subprocess hierarchy. In a multilevel hierarchy, the root process can differ from the subprocess's immediate parent.

Can I check if a parameter exists?

CheckParameter can be used when existence is checked together with an expected value. It returns false when the parameter does not exist, regardless of CompareType, and otherwise evaluates the configured comparison. For a direct existence check, prefer ProcessInstance.IsParameterExisting in a custom condition or use an expression condition.