Expressions
Learn how to use expressions in Elsa Studio to reference variables, access data, and create dynamic workflows with JavaScript and C# code.
Expressions are one of the most powerful features in Elsa Studio. They allow you to write dynamic values for activity properties, reference workflow variables, perform calculations, and make data-driven decisions in your workflows.
This guide covers how to use expressions in Studio, with a focus on JavaScript and C# expressions for working with variables.
Expression Types in Studio
When configuring an activity property in Studio, you can choose from several expression types:
Literal
A Literal expression is a static value that doesn't change. Use this when you want to hardcode a value.
Example: Setting a variable to the text "Hello, World!"
JavaScript
JavaScript expressions let you write JavaScript code to compute values dynamically. This is the most commonly used expression type for referencing variables and performing simple operations.
Example: variables.OrderId or variables.Customer.Name
C#
C# expressions let you write C# code with full access to .NET types and methods. Use this when you need strong typing, complex logic, or access to .NET libraries.
Example: Variable.Get<Guid>("OrderId") or Variable.OrderId
JSON
JSON expressions allow you to provide JSON data directly. This is useful when working with structured data.
Liquid
Liquid is a template language that's useful for generating text with embedded variables.
Example: Hello, {{ Variables.CustomerName }}!
Other Expression Types
Elsa also supports Python and other expression types depending on your server configuration. Check your Elsa Server's installed packages to see what's available.
How to Choose an Expression Type
In the Studio property panel, you'll see a dropdown next to each property where you can select the expression type:
![Studio screenshot placeholder]
When to use each type:
Literal: Simple static values (numbers, strings, booleans)
JavaScript: Quick variable access, simple calculations, most common use case
C#: Complex logic, strong typing, access to .NET libraries
JSON: Structured data objects
Liquid: Text templates with variables
Understanding the Variables Object
In Elsa workflows, variables are stored in a special variables object that's accessible in expressions. The structure of this object depends on how you've defined your variables.
Variable Structure
When you create a variable in your workflow, it becomes a property on the variables object:
Variable name:
OrderId→ Access as:variables.OrderIdVariable name:
CustomerName→ Access as:variables.CustomerNameVariable name:
variable1→ Access as:variables.variable1
Object Variables
Variables can store complex objects with nested properties. For example, if you have a variable called variable1 that contains an object with a data property:
// Variable structure
variable1 = {
data: {
id: "12345",
name: "Example"
}
}You can access nested properties using dot notation:
variables.variable1.data.idReferencing Variables in JavaScript Expressions
JavaScript expressions are the most common way to work with variables in Studio. Here's how to use them effectively.
Reading a Simple Variable
To read a variable value, use the variables object:
JavaScript:
variables.OrderIdReading Nested Properties
For variables that contain objects, use dot notation to access nested properties:
JavaScript:
variables.variable1.data.id
variables.Customer.Address.City
variables.OrderDetails.Items[0].PriceSetting a Variable Value
The variables object is read-only in most contexts. To set variables, use the SetVariable activity or the setVariable() function:
JavaScript:
setVariable("OrderId", newGuid())Using Variables in Calculations
You can perform calculations with variable values:
JavaScript:
variables.Quantity * variables.UnitPrice
variables.FirstName + " " + variables.LastName
variables.TotalAmount > 1000Handling Null or Undefined Variables
Always be careful when accessing variables that might not exist:
JavaScript:
// Check if variable exists before using it
variables.OrderId ? variables.OrderId : "default-value"
// Or use optional chaining (if supported)
variables.Customer?.Address?.City
// Provide a default value
variables.OrderId || "unknown"Referencing Variables in C# Expressions
C# expressions provide type safety and access to the full .NET framework. There are several ways to access variables in C#.
Strongly-Typed Access
If your variable is defined in the workflow, Elsa generates strongly-typed properties on the Variable object:
C#:
Variable.OrderId
Variable.CustomerNameThis approach provides compile-time type checking and IntelliSense support.
Using Variable.Get()
You can access variables by name with type safety using the Get<T>() method:
C#:
Variable.Get<Guid>("OrderId")
Variable.Get<string>("CustomerName")
Variable.Get<int>("Quantity")Dynamic Access
For variables with complex structures or when you need more flexibility:
C#:
// Using the variables dictionary (requires casting)
var variable1 = Variable.Get<dynamic>("variable1");
var id = variable1.data.id;
// Or access as an object and cast
var customerObj = Variable.Get<object>("Customer");Dictionary-Based Access
When working with object variables that are stored as dictionaries:
C#:
var variable1 = Variable.Get<Dictionary<string, object>>("variable1");
var data = variable1["data"] as Dictionary<string, object>;
var id = data["id"] as string;Setting Variables in C#
Use the Set() method to assign values:
C#:
Variable.Set("OrderId", Guid.NewGuid());
Variable.Set("Status", "Completed");Practical Example: Using SetVariable Activity
This example demonstrates the scenario from issue #89: reading a nested property from an object variable and using it to set another variable.
Scenario
You have a variable called variable1 that contains an object:
{
"data": {
"id": "abc-123",
"name": "Sample Item"
}
}Goal: Extract the id value and store it in a new variable called extractedId.
Solution with JavaScript
Add a
SetVariableactivity to your workflowConfigure the activity:
Variable Name:
extractedId(Literal)Value: Choose JavaScript as the expression type
Expression:
variables.variable1.data.id![Studio screenshot placeholder]
This reads the id property from the nested data object within variable1 and assigns it to extractedId.
Solution with C# (Using Get Method)
Using the Get<T>() method with type casting:
Add a
SetVariableactivityConfigure the activity:
Variable Name:
extractedId(Literal)Value: Choose C# as the expression type
Expression:
Variable.Get<dynamic>("variable1").data.idDynamic vs Strongly-Typed: Using dynamic bypasses compile-time type checking, which means potential errors won't be caught until runtime. Use dynamic access when the variable structure is truly unknown at design time, but prefer strongly-typed access (with Variable.Get<T>() and specific types) when you know the structure for better safety and IntelliSense support.
Solution with C# (Dictionary Access)
If you need more control over type handling, use dictionary access:
Add a
SetVariableactivityConfigure the activity:
Variable Name:
extractedId(Literal)Value: Choose C# as the expression type
Expression:
var variable1 = Variable.Get<Dictionary<string, object>>("variable1");
var data = variable1["data"] as Dictionary<string, object>;
var id = data?["id"] as string;
return id ?? string.Empty;Null Safety: When using the as operator for casting, always check for null values. The example above uses the null-conditional operator (?.) and null-coalescing operator (??) to safely handle cases where the cast might fail or values might be missing. Without these checks, you risk NullReferenceException at runtime.
When using dynamic access or dictionaries, you may need to cast values to the appropriate type. The exact approach depends on how your variable was created and what type of data it contains.
More Complex Examples
Combining Multiple Variables
JavaScript:
`${variables.FirstName} ${variables.LastName} - Order #${variables.OrderId}`C#:
$"{Variable.FirstName} {Variable.LastName} - Order #{Variable.OrderId}"Conditional Logic
JavaScript:
variables.TotalAmount > 1000 ? "Premium" : "Standard"C#:
Variable.TotalAmount > 1000 ? "Premium" : "Standard"Working with Arrays
JavaScript:
// Get first item
variables.Items[0].Name
// Get array length
variables.Items.length
// Check if array contains value
variables.Tags.includes("urgent")C#:
// Get first item
Variable.Get<List<Item>>("Items")[0].Name
// Get count
Variable.Get<List<Item>>("Items").Count
// Check if contains
Variable.Get<List<string>>("Tags").Contains("urgent")Evaluation Context and Common Pitfalls
Understanding where expressions are evaluated helps avoid common errors.
Where Variables Come From
The variables object is constructed by the Elsa workflow engine at runtime. It contains:
Variables defined in your workflow definition
Variables set by activities during execution
Variables passed as workflow input
Variables are stored in the workflow instance state and persist across workflow executions if the workflow is suspended and resumed.
Common Pitfalls
1. Misspelled Variable Names
Problem: variables.OrderID when the variable is actually called OrderId
Solution: Variable names are case-sensitive. Double-check the exact spelling in your workflow definition.
2. Wrong Expression Type
Problem: Setting a property to "Literal" when you meant to use "JavaScript"
Solution: Always verify the expression type dropdown is set correctly. If your expression looks like code but isn't evaluated, you probably have it set to "Literal".
3. Null Reference Errors
Problem: Accessing variables.Customer.Name when Customer is null
Solution: Use null-checking:
JavaScript:
variables.Customer?.Nameorvariables.Customer && variables.Customer.NameC#:
Variable.Customer?.Name
4. Variable Not Found
Problem: Variable doesn't exist yet when you try to access it
Solution: Ensure the variable is:
Defined in your workflow definition, OR
Set by a previous activity that has already executed
Variables are only available after they've been created or set.
5. Type Mismatches in C#
Problem: Trying to access a string variable as an integer
Solution: Use the correct type parameter in Get<T>():
Variable.Get<int>("Quantity") // Not Variable.Get<string>("Quantity")Accessing Activity Outputs
In addition to variables, you can access outputs from other activities in your workflow.
Using JavaScript
Access by activity name:
getOutputFrom("MyHttpRequest", "Body")Access last result:
getLastResult()Using C#
Access by activity name:
Output.From<string>("MyHttpRequest", "Body")Access last result:
Output.LastResultAccessing Workflow Input
If your workflow receives input when it starts, you can access it in expressions.
Using JavaScript
getInput("OrderId")Or use the shorthand getter:
getOrderId()Using C#
Input.Get<Guid>("OrderId")Or use strongly-typed access:
Input.OrderIdTesting Your Expressions
To test expressions:
Run Your Workflow: Execute the workflow in Studio
Check Instances: Go to "Workflow Instances" in the sidebar
Inspect Variables: Open the workflow instance and view the variables tab
Look for Errors: If an expression fails, check the workflow instance for error messages
Best Practices
Choose the Right Expression Type
Use Literal for static values
Use JavaScript for simple variable access and logic
Use C# when you need type safety or complex .NET operations
Name Variables Clearly
Use descriptive variable names that indicate what they contain:
✅
OrderId,CustomerEmail,TotalAmount❌
var1,temp,x
Handle Null Cases
Always consider whether a variable might be null or undefined:
JavaScript:
variables.OptionalField || "default value"C#:
Variable.OptionalField ?? "default value"Use Strongly-Typed Access in C#
When possible, define variables in your workflow and use strongly-typed access for better IntelliSense and compile-time checking.
Keep Expressions Simple
If an expression becomes too complex, consider breaking it into multiple activities. This makes your workflow easier to understand and debug.
Additional Resources
C# Expressions Reference: Complete reference for C# expressions in Elsa
JavaScript Expressions Reference: Complete reference for JavaScript expressions in Elsa
Workflow Variables API: Working with variables programmatically
Studio User Guide: Overview of Elsa Studio features
Summary
Expressions in Elsa Studio give you the power to create dynamic, data-driven workflows. By understanding how to:
Choose the right expression type
Access variables using
variables.VariableNameReference nested properties with dot notation
Handle null cases and type conversions
Use both JavaScript and C# expressions effectively
You can build sophisticated workflows that respond to data and conditions in your business processes.
You're Ready! With this knowledge, you can confidently use expressions in your workflows. Start simple with variable references, then gradually add more complex logic as needed.
Last updated