When I started with Microsoft Flow, I started with understanding triggers and actions. Then quite quickly I discovered dynamic content and expressions. Data moves from one a step to another with ease but sometimes things get a bit harder.In this post I will look at the input and the output of each step in Microsoft Flow.
Getting dynamic content data from Triggers
Table of Contents
I will start by looking at a simple example using a SharePoint trigger and a Compose action and an initialize variable action.
In my Compose action I’m seeing a lot of Dynamic content option appear
When I do the same in my initialize variable action I’m only seeing a few options appear.
Type checks
The big difference here is that the initialize variable action is checking the type of the dynamic content and only Boolean data is shown. The earlier compose example doesn’t check the type of the data and therefore it is happy to give you any of the data returned by the trigger or previous actions. For the compose action and the variable actions this might all be quite obvious,but how about other actions?
When the Id field is used only ID of the trigger will appear. It looks like this field is checking for the type of field too.
Checking the type of data is great as it avoids silly mistakes, but sometimes it can work against you. Imagine if you have a text field and you would like to add the ID of the list item? Well, Dynamic content will not help you there.
JSON output from the triggerBody function
First of all I want to understand the data that was returned by my trigger.By using a Compose action and using the triggerBody function I’m collecting all information returned by my trigger.
When I now look at my trigger output in the compose action I get something like this:
[code lang=text]
{
"@odata.etag": "\"2\"",
"ItemInternalId": "94",
"ID": 94,
"Modified": "2018-12-06T10:20:50Z",
"Editor": {
"@odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
"Claims": "i:0#.f|membership|pieter@pieterveenstramvp.onmicrosoft.com",
"DisplayName": "Pieter Veenstra",
"Email": "pieter@PieterVeenstraMVP.onmicrosoft.com",
"Picture": "https://pieterveenstramvp.sharepoint.com/_layouts/15/UserPhoto.aspx?Size=L&AccountName=pieter@PieterVeenstraMVP.onmicrosoft.com",
"Department": "",
"JobTitle": ""
},
"Editor#Claims": "i:0#.f|membership|pieter@pieterveenstramvp.onmicrosoft.com",
"Yes": true,
"Created": "2018-12-06T10:20:50Z",
"Author": {
"@odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
"Claims": "i:0#.f|membership|pieter@pieterveenstramvp.onmicrosoft.com",
"DisplayName": "Pieter Veenstra",
"Email": "pieter@PieterVeenstraMVP.onmicrosoft.com",
"Picture": "https://pieterveenstramvp.sharepoint.com/_layouts/15/UserPhoto.aspx?Size=L&AccountName=pieter@PieterVeenstraMVP.onmicrosoft.com",
"Department": null,
"JobTitle": null
},
"Author#Claims": "i:0#.f|membership|pieter@pieterveenstramvp.onmicrosoft.com",
"{Identifier}": "Shared%2bDocuments%252fRecordings.PNG",
"{IsFolder}": false,
"{Link}": "https://pieterveenstramvp.sharepoint.com/Shared%20Documents/Recordings.PNG",
"{Name}": "Recordings",
"{FilenameWithExtension}": "Recordings.PNG",
"{Path}": "Shared Documents/"
}
[/code]
The above json gives me all the data for the item that triggered my flow. Note that this doesn’t include all the data. Only fields that have been set will be returned here. e.g. my list has a field called Choices but this field isn’t included in my JSON. Only after I updated my choices field I see the below inserted in my triggerBody output:
[code lang=text]
"Choices": {
"@odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedReference",
"Id": 0,
"Value": "Choice 1a"
},
[/code]
Getting to your data
This now makes it a lot easier to get to the data that you want to get to. Taking the output from the compose action we can use the outputs function
[code lang=text]
outputs('Compose')
[/code]
All we have to do is feed the name of the action that we want to get the output from. Ok, the above example doesn’t look very exciting and I would even say this is a bit too far on the techie / geeky side.
But if we wanted to get to the Choices data we could simply use the following expression:
[code lang=text]
outputs('Compose')?['Choices']
[/code]
Taking this a step further we could even get the Id or Value of the selected choice:
[code lang=text]
outputs('Compose')?['Choices']?['Id']
outputs('Compose')?['Choices']?['Value']
[/code]
Ok, the Value you might be able to get to using dynamic content but the Id of the Choice you can’t get to any other way than using expressions. More importantly by using the functions I can avoid the type check that the designer enforces. When for example I send out an email, I might want to include numbers in the body of my email even though my email body is text. Using expressions to get to things works well.
Important functions
There are a few important functions that you might also want to be aware of
- trigger
- action
- body
The trigger functions returns information on the trigger action and it actually gives you a lot more than the trigger body.
An example of the trigger function output is shown below. Ok, there is a lot of junk here, but a start time of the flow is something that you could now get out of your trigger. These fucnitons might just help you get to the bits that are hidden away from most users.
[code lang=text]
{
"name": "When_a_file_is_created_or_modified_(properties_only)",
"inputs": {
"host": {
"api": {
"runtimeUrl": "https://uk-001.azure-apim.net/apim/sharepointonline"
},
"connection": {
"name": "/providers/Microsoft.PowerApps/apis/shared_sharepointonline/connections/shared-sharepointonl-f7fad2c2-d18c-4d24-9fc1-a3b535607255"
}
},
"method": "get",
"path": "/datasets/https%253A%252F%252Fpieterveenstramvp.sharepoint.com%252F/tables/a8bcb564-c8f1-4c88-9324-bb872bd6bbfc/onupdatedfileitems",
"authentication": {
"scheme": "Key",
"parameter": "*sanitized*",
"type": "Raw"
}
},
"outputs": {
"headers": {
"Transfer-Encoding": "chunked",
"Retry-After": "3600",
"Vary": "Accept-Encoding",
"X-SharePointHealthScore": "0",
"X-MS-SPConnector": "1",
"X-SP-SERVERSTATE": "ReadOnly=0",
"DATASERVICEVERSION": "3.0",
"SPClientServiceRequestDuration": "68",
"SPRequestGuid": "4d59a99e-f0f0-0000-4a34-e6795aa4b52d",
"request-id": "4d59a99e-f0f0-0000-4a34-e6795aa4b52d",
"MS-CV": "nqlZTfDwAABKNOZ5WqS1LQ.0",
"Strict-Transport-Security": "max-age=31536000",
"X-FRAME-OPTIONS": "SAMEORIGIN",
"MicrosoftSharePointTeamServices": "16.0.0.8328",
"X-Content-Type-Options": "nosniff",
"X-MS-InvokeApp": "1; RequireReadOnly",
"Timing-Allow-Origin": "*",
"x-ms-apihub-cached-response": "true",
"Cache-Control": "max-age=0, private",
"Date": "Thu, 06 Dec 2018 12:04:51 GMT",
"Location": "https://uk-001.azure-apim.net/apim/sharepointonline/shared-sharepointonl-f7fad2c2-d18c-4d24-9fc1-a3b535607255/datasets/https%253A%252F%252Fpieterveenstramvp.sharepoint.com%252F/tables/a8bcb564-c8f1-4c88-9324-bb872bd6bbfc/onupdatedfileitems?triggerstate=ZGF0ZXRpbWU9MjAxOC0xMi0wNlQxMjowNDo0N1o%3d",
"P3P": "CP=\"ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI\"",
"Set-Cookie": "SPWorkLoadAttribution=Url=https://pieterveenstramvp.sharepoint.com/_api/SP.APIHubConnector.InvokeQuery&AppId=E0D3C05D-9133-40D1-8413-1C4522A4E7C2; expires=Thu, 06-Dec-2018 12:05:22 GMT; path=/",
"X-AspNet-Version": "4.0.30319",
"X-Powered-By": "ASP.NET",
"Content-Type": "application/json; charset=utf-8",
"Expires": "Wed, 21 Nov 2018 12:04:52 GMT",
"Last-Modified": "Thu, 06 Dec 2018 12:04:52 GMT",
"Content-Length": "1930"
},
"body": {
"@odata.etag": "\"7\"",
"ItemInternalId": "94",
"ID": 94,
"Modified": "2018-12-06T12:04:46Z",
"Editor": {
"@odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
"Claims": "i:0#.f|membership|pieter@pieterveenstramvp.onmicrosoft.com",
"DisplayName": "Pieter Veenstra",
"Email": "pieter@PieterVeenstraMVP.onmicrosoft.com",
"Picture": "https://pieterveenstramvp.sharepoint.com/_layouts/15/UserPhoto.aspx?Size=L&AccountName=pieter@PieterVeenstraMVP.onmicrosoft.com",
"Department": "",
"JobTitle": ""
},
"Editor#Claims": "i:0#.f|membership|pieter@pieterveenstramvp.onmicrosoft.com",
"Some_x0020_Text": "test",
"Yes": true,
"Choices": {
"@odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedReference",
"Id": 0,
"Value": "Choice 1a"
},
"Choices#Id": 0,
"lookup": {
"@odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedReference",
"Id": 2,
"Value": "test number 3"
},
"lookup#Id": 2,
"MediaServiceAutoTags": "screenshot",
"MediaServiceOCR": "My Test Team\nMy Test Tearn\nHighlights\nVideos\nChannels\nMembership\nT t'iteo\nSee more\nLATEST VIDEOS\nMy test meeting\nMy test meeting",
"OData__x0024_Resources_x003a_core_x002c_Signoff_Status_x003b_": "test",
"Created": "2018-12-06T10:20:50Z",
"Author": {
"@odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
"Claims": "i:0#.f|membership|pieter@pieterveenstramvp.onmicrosoft.com",
"DisplayName": "Pieter Veenstra",
"Email": "pieter@PieterVeenstraMVP.onmicrosoft.com",
"Picture": "https://pieterveenstramvp.sharepoint.com/_layouts/15/UserPhoto.aspx?Size=L&AccountName=pieter@PieterVeenstraMVP.onmicrosoft.com",
"Department": null,
"JobTitle": null
},
"Author#Claims": "i:0#.f|membership|pieter@pieterveenstramvp.onmicrosoft.com",
"{Identifier}": "Shared%2bDocuments%252fRecordings.PNG",
"{IsFolder}": false,
"{Link}": "https://pieterveenstramvp.sharepoint.com/Shared%20Documents/Recordings.PNG",
"{Name}": "Recordings",
"{FilenameWithExtension}": "Recordings.PNG",
"{Path}": "Shared Documents/"
}
},
"startTime": "2018-12-06T12:13:28.1420329Z",
"endTime": "2018-12-06T12:13:28.1420329Z",
"trackingId": "dbc42c4a-5283-4a03-9970-455366a7075b",
"clientTrackingId": "08586575089934559844914214268CU07",
"clientKeywords": [
"testFlow"
],
"status": "Succeeded"
}
[/code]
For more details on these functions, please have a look at the Microsoft Documentation on Workflow functions