# 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](https://docs.workflowengine.io/images/plugins/basic-plugin/managing-parameters/manage-parameters.png) **Related capabilities:** `SetParameter` action, `RemoveParameter` action, `CheckParameter` condition, `Otherwise` condition type. ```xml filename="manage-parameters.xml" ``` ### How the scheme works Once the scheme is saved and the `BasicPlugin` is registered with the `WorkflowRuntime`, the process runs as follows: ```csharp // 1. Create an instance from the scheme var 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 command var 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 status var 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. | Parameter | Required | Default | Description | |---|---|---|---| | `ParameterName` | Yes | - | Name of the parameter to set. | | `Value` | Yes | - | 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()`. | | `ForRootProcess` | Yes | `false` | When `true`, operates on the root process parameter in a subprocess hierarchy. | ### RemoveParameter action Deletes a process parameter by name. | Parameter | Required | Default | Description | |---|---|---|---| | `ParameterName` | Yes | - | Name of the parameter to remove. | | `ForRootProcess` | Yes | `false` | When `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. | Parameter | Required | Default | Description | |---|---|---|---| | `ParameterName` | Yes | - | Name of the parameter to check. | | `CompareType` | Yes | `Equal` | Comparison operator. See [CompareType](#comparetype) enum. | | `Value` | No | Empty string | Value to compare against. For `In`/`NotIn`, use a delimited list. | | `Separator` | Yes | `,` | Delimiter for `In`/`NotIn` comparison. | | `ForRootProcess` | Yes | `false` | When `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. | Value | Example | |-------|---------| | `Equal` | n == v | | `NotEqual` | n != 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" | | `Greater` | n > v | | `Less` | n < v | | `GreaterOrEqual` | n >= v | | `LessOrEqual` | n <= v | | `In` | 5 in (1, 2, 3, 4, 5) | | `NotIn` | 6 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 - [Basic Plugin Overview](https://docs.workflowengine.io/plugins/basic-plugin/overview/): Registration, configuration, and full API reference. - [HTTP Requests](https://docs.workflowengine.io/plugins/basic-plugin/http-requests/): Send HTTP requests and branch on responses. - [Process Control](https://docs.workflowengine.io/plugins/basic-plugin/process-control/): Jump between activities and control process state. ## 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.