Sharepoint 2013 App Workflow Weird Part #2: DynamicValue is more dynamicky than you might think

Let’s start the story with a look at REST calls. SharePoint 2013 Workflows include a HttpSend activity that can be used to make REST calls (as an aside, I’ve found it to be more flexible and dependable than some of the native workflow activities when it comes to manipulating SharePoint data). The basic recipe for making a REST call from a SharePoint 2013 Workflow looks like this:

  • Use an HttpSend activity to call to the REST endpoint (Note that if you’re doing POSTs, you will need a Form Digest; see this article for more details)
  • Use an If conditional activity to confirm an HttpStatusCode of OK
  • If OK, then use ParseDynamicValue activity to convert the JSON response into a DynamicValue object
  • Use GetDynamicValueProperties activity to read values into variables using paths

With a little practice (and perhaps a well-placed query or two to your search engine of choice) calls like this will become second nature. However, sooner or later something unanticipated happens. In particular, what happens if the returned result is an array of values?

Thats exactly what happened to me. I had a scenario where I issued a REST query to get back all the members of a SharePoint group; naturally, those values are returned as an array. Here’s the query I issued:

_api/web/sitegroups/getbyname('{group name}')/Users

And here’s the JSON result that came back:

{"d":
     {"results":
          [
               {"__metadata":
                    {"id":"http://app-38fea3cc91f3d1.labsdevapps.local/AbsenceandVacationManagement/_api/Web/GetUserById(1)",
                    "uri":"http://app-38fea3cc91f3d1.labsdevapps.local/AbsenceandVacationManagement/_api/Web/GetUserById(1)",
                    "type":"SP.User"},
               "Groups":{"__deferred":{"uri":"http://app-38fea3cc91f3d1.labsdevapps.local/AbsenceandVacationManagement/_api/Web/GetUserById(1)/Groups"}},
               "Id":1,
               "IsHiddenInUI":false,
               "LoginName":"i:0#.w|labsdev\sp_admin",
               "Title":"SP_Admin",
               "PrincipalType":1,
               "Email":"",
               "IsSiteAdmin":false,
               "UserId":
                    {"__metadata":{"type":"SP.UserIdInfo"},
                    "NameId":"s-1-5-21-1407570785-1617640577-437752984-1105",
                    "NameIdIssuer":"urn:office:idp:activedirectory"}
               }
          ]
     }
}

Note the square brackets after the “results” node, indicating that we’re dealing with an array. So, clever guy that I am, I tried a couple of remedies:

  • Put the result in an Array of DynamicValue objects
  • Put the result in a Collection of DynamicValue objects

Sadly, both of these suffered the same fate: they would build, but would not deploy. So then someone much smarter than me made a suggestion, and the conversation went something like this:

Smart Person: “why not just put d/results into a DynamicValue object?”
Me: “Wait, WHAT?!?!”

Turns out Smart Person was right.

After performing our HttpSend activity, checking the status, and parsing the JSON response into our initial DynamicValue, we establish a new variable for containing our array:

Then, we use a GetDynamicValueProperties activity and read the array into our new DynamicValue variable:

We add a ForEach loop activity to iterate through the data:

Take note that we are not doing any kind of expression in what we are looping through, like .Keys or .Values.  (I actually tried that at some point);  we’re just telling the workflow to loop through each DynamicValue inside a DynamicValue, and it just knows what to do (quite odd, isn’t it?).  Once inside the loop, we can then path to our values out of our DynamicValue:

For those of you that like to plumb the depths for greater understanding, you can see Microsoft’s class definition to learn more about the behavior of DynamicValue; for those that just want it to work, remember the DynamicValue object can be used to parse an array within another DynamicValue object (weird, RIGHT?).