Working with complex data in a workflow
Updated: July 12, 2012
DynamicValue
allows you to create, store, and consume data structures. This data can be recursive, meaning that a DynamicValue
can contain other DynamicValues
. DynamicValue
composition rules are very simple: its properties can be primitives, arrays, or other DynamicValues
, similar to a recursive property bag or JSON serialization format. DynamicValue
provides both a container and manipulation mechanism for compound data with first class binding surface for WF.
How DynamicValue Stores its Data
At the very core, you can think of DynamicValue
as a recursive list of key-value pairs. The following table represents a simple DynamicValue
:
Name | Value of Underlying Primitive Data Type |
---|---|
Age | 42 |
Name | John Doe |
In the previous table, the DynamicValue
has two properties: Age
has a value of 42
and Name
has a value of John Doe
. The name of a DynamicValue
property is a string, and the value can be any one of the types in the following list, or null
(Nothing
in Visual Basic). If any other type is passed to a DynamicValue
an exception will be thrown.
String
Int32
Double
Guid
Boolean
DateTime
TimeSpan
IList<T>, where T is one of the types in this list
IDictionary<string, T>, where T is one of the types in this list
DynamicValue
Note that DynamicValue
is in the list of supported types. This means that the value of a DynamicValue
can be another DynamicValue
, as shown in the following table.
Name | Value |
---|---|
Customer | Age - 42 Name - Jon Doe |
Company | Contoso Corporation |
Customer
contains a DynamicValue
as its value, and that DynamicValue
contains Age
and Name
. To reference the value for Name
, you can use Customer/Name
. If Customer/Name
value is referred to and it has not yet been created, it will be added. This is referred to as an upsert
.
DynamicValue
also supports the notion of arrays. An array is a set of primitive values contained as the value for a DynamicValue
. The main conceptual difference between a DynamicValue
as an array instead of nested DynamicValue
is that the items in the array do not have a name and are accessed by index. Note that the arrays can contain different types. In the array value for Numbers
, the types are Int32
and Double
. In the array value for Items
, the values are a nested DynamicValue
and an Int32
.
Name | Value |
---|---|
Numbers | 4 6 3 3.14 2.71 |
Items | First - 4 Second - 5 6 |
Addressing Values in a DynamicValue
Values are set and retrieved from a DynamicValue
using a path notation. Paths are Uri
-like strings that point to a given property, similar to the flattened representation of a structure. Paths are composed using the name of a property, using a string, or an index into an item within an array value, using a number surrounded by parenthesis.
Note
To see examples of working with DynamicValue paths, see the DynamicValue Path Evaluator sample. The DynamicValue Path Evaluator sample allows you to enter the endpoint of a REST service that returns JSON, and experiment and become familiar with DynamicValue and paths of the returned data.
In the previous section, several examples of DynamicValue
were given. The first example was for a DynamicValue
with two values, as shown in the following table.
Name | Value |
---|---|
Age | 42 |
Name | John Doe |
To access the first value, a path consisting of Age
is used, which returns a value of 42
. A path of Name
returns the value John Doe
.
The second example from the previous section included some nested values, as shown in the following table.
Name | Value |
---|---|
Customer | Age - 42 Name - Jon Doe |
Company | Contoso Corporation |
The path Customer
returns a DynamicValue
(which itself contains two values). The path of Company
returns Contoso Corporation
. In order to access nested values, a /
is used to delineate properties. Using this notation, the path Customer/Age
returns a value of 42
, and Customer/Name
returns John Doe
.
To access values stored in an array, indexes are used in the path. The following table represents the DynamicValue
from the previous section that contained booth arrays and nested DynamicValues
.
Name | Value |
---|---|
Numbers | 4 6 3 3.14 2.71 |
Items | First - 4 Second - 5 6 |
In the DynamicValue
represented by the previous table, a path of Numbers
returns the first array. DynamicValue
arrays are zero based, and Numbers(0)
returns the first element of the array, and Numbers(3)
returns the fourth element of the array. Items
returns the second array, and Items(0)
returns the first item in the array, which is a DynamicValue
. To access the values in that nested DynamicArray
, the property names are combined with the path that yields the array. Items(0)/First
returns 4
and Items(0)/Second
returns 5
.
You can use paths to declaratively build a compound data structure. The values can be known at design time or dynamically bound at runtime. The following example shows a set of paths and values that represent a composition of a customer that has an address.
Path (To) | Value (From) |
---|---|
FirstName | John |
LastName | Doe |
Address/City | Redmond |
Address/State | WA |
The paths and values in the previous table would create the DynamicValue
represented by the following table.
Name | Value |
---|---|
FirstName | John |
LastName | Doe |
Address | City - Redmond State - WA |
The DynamicValue
type provides a Parse
method that can be used to parse a JSON
string into a DynamicValue
. In addition, there is a ParseDynamicValue
activity that can be used in workflows to parse a JSON
string into a DynamicValue
.
Http activities can also understand DynamicValue
. If you assign a DynamicValue
to the response of an Http* activity, it will get the results as JSON
and build a DynamicValue
with that result. If you pass a DynamicValue
to the request body or use it as the response content, the appropriate headers will be added to indicate that JSON
is used.
Using DynamicValue in Workflows
In addition to the DynamicValue
type, Workflow Manager 1.0 also provides activities for creating and working with DynamicValue
in workflows.
Activity | Description | Arguments |
---|---|---|
BuildDynamicValue | Builds a DynamicValue instance. It receives a dictionary of paths and values as input and returns the resulting DynamicValue. It uses a multi-assign approach to build the DynamicValue (it accepts multiple paths and values). This activity can be used to create a new DynamicValue or to modify an existing one. |
InArgument<IDictionary<string,InArgument>> Properties InOutArgument<DynamicValue> Result |
ContainsDynamicValueProperty | Returns true if a DynamicValue contains a property represented by the specified path | InArgument<DynamicValue> Source InArgument<DynamicValue> PropertyName OutArgument<bool> Result |
CopyDynamicValue | Copies properties from one DynamicValue to another DynamicValue | InArgument<IDictionary<string,string>> PropertyMapping InArgument<DynamicValue> Source OutArgument<DynamicValue> Result |
CountDynamicValueItems | Returns the count of children in a DynamicValue path | InArgument<DynamicValue> Source OutArgument<int> Result |
CreateDynamicValue | Create an instance of a DynamicValue passing only one path and one value (no multi-assign semantics) | InArgument<string> PropertyName InArgument PropertyValue OutArgument<DynamicValue> Result |
T:Microsoft.Activities.CreateDynamicValueFromMessage | Creates a DynamicValue from a SOAP message | InArgument<DynamicValue> Headers InArgument<XElement> Value InArgument<MessageVersion> Version OutArgument<DynamicValue> Result |
T:Microsoft.Activities.CreateMessageFromDynamicValue | Creates a SOAP message from a specially formatted DynamicValue | InArgument<string> Action InArgument<DynamicValue> Headers InArgument<DynamicValue> Body InArgument<MessageVersion> Version OutArgument<XElement> Result |
CreateUriFromDynamicValue | Creates a URI from a DynamicValue | InArgument<DynamicValue> Options OutArgument<string> Result |
GetDynamicValueProperties | Get several properties of an existing DynamicValue. Given a DynamicValue a user can query multiple properties (passing multiple paths) using a single activity. | InArgument<DynamicValue> Source InArgument<IDictionary<string,OutArgument>> Properties |
GetDynamicValueProperty<T> | Get one property of a DynamicValue, where T is one of the types in previously given list. | InArgument<DynamicValue> Source InArgument<string> PropertyName OutArgument<T> Result |
ParseDynamicValue | Parse a JSON string into a DynamicValue | InArgument<string> JSON OutArgument<DynamicValue> Result |
Using DynamicValue
DynamicValue
and its supporting activities allow for representing and manipulating data in a host agnostic way. Hence, DynamicValue
is a workflow feature that can be used with any workflow host, so it is not limited to Workflow Manager 1.0. It can be used with any of the other existing workflow hosts like WorkflowInvoker
, WorkflowApplication
, and WorkflowServiceHost
.
The Working with complex data in a workflow using DynamicValue sample demonstrates how to use the feature with WorkflowApplication
. Several of the other Using DynamicValue samples show how to use DynamicValue
in Workflow Manager 1.0 workflows. DynamicValue
usage is the same regardless of the host; what changes for every host is how the data is loaded into the DynamicValue
(for example in Workflow Manager 1.0 it is very common to create the DynamicValue
as the result of an Http operation using Http activities).
Note
For information about the Workflow Manager 1.0 samples and where to locate them, see Samples.