Issue with Azure Logic APP EPOCH DATE Conversion - azure

I have an issue with epoch date conversion in Azure logic app.
I cannot figure out what I'm doing wrong here.
I have divided my logic app in different steps to first get the Timestamp and remove "/Date" and the trailing "/".
And then I use the add to time function where i am getting an unexpected result.
Input:
"EndDate": "/Date(253402214400000)/",
"StartDate": "/Date(946684800000)/"
Expected output
"EndDate" : "2000-01-01T00:00:00",
"StartDate": "9999-12-31T00:00:00"
Current result:
"EndDate": "1942-11-15T20:26:40.0000000Z",
"StartDate": "2026-10-14T16:21:20.0000000Z"
Logic app code
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Compose": {
"inputs": {
"root": {
"CostAccountID": "AD100",
"EndDate": "9999-12-31T00:00:00Z",
"StartDate": "2000-01-01T00:00:00Z"
}
},
"runAfter": {},
"type": "Compose"
},
"Compose_2": {
"inputs": {
"root": {
"CostAccountID": "#{body('Parse_JSON')?['root']?['CostAccountID']}",
"EndDate1": "#{int(replace(replace(body('Parse_JSON')?['root']?['EndDate'],'/Date(',''),')/',''))}",
"StartDate1": "#{int(replace(replace(body('Parse_JSON')?['root']?['StartDate'],'/Date(',''),')/',''))}"
}
},
"runAfter": {
"Parse_JSON": [
"Succeeded"
]
},
"type": "Compose"
},
"Compose_3": {
"inputs": {
"root": {
"CostAccountID": "#{body('Parse_JSON')?['root']?['CostAccountID']}",
"EndDate": "#{addToTime('1970-01-01T00:00:00Z', int(body('Parse_JSON_2')?['root']?['EndDate1']), 'Second')}",
"StartDate": "#{addToTime('1970-01-01T00:00:00Z', int(body('Parse_JSON_2')?['root']?['StartDate1']), 'Second')}"
}
},
"runAfter": {
"Parse_JSON_2": [
"Succeeded"
]
},
"type": "Compose"
},
"Parse_JSON": {
"inputs": {
"content": "#outputs('Compose')",
"schema": {
"properties": {
"root": {
"properties": {
"CostAccountID": {
"type": "string"
},
"EndDate": {
"type": "string"
},
"StartDate": {
"type": "string"
}
},
"type": "object"
}
},
"type": "object"
}
},
"runAfter": {
"Compose": [
"Succeeded"
]
},
"type": "ParseJson"
},
"Parse_JSON_2": {
"inputs": {
"content": "#outputs('Compose_2')",
"schema": {
"properties": {
"root": {
"properties": {
"CostAccountID": {
"type": "string"
},
"EndDate1": {
"type": "string"
},
"StartDate1": {
"type": "string"
}
},
"type": "object"
}
},
"type": "object"
}
},
"runAfter": {
"Compose_2": [
"Succeeded"
]
},
"type": "ParseJson"
},
"Response": {
"inputs": {
"body": "#outputs('Compose_2')",
"statusCode": 200
},
"kind": "http",
"runAfter": {
"Compose_3": [
"Succeeded"
]
},
"type": "Response"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"triggers": {
"manual": {
"inputs": {},
"kind": "Http",
"type": "Request"
}
}
},
"kind": "Stateful"
}

After reproducing from my end, we have observed that you have used the value in milliseconds. Try converting it into seconds and follow the same approach. Below is the code I'm using -
{
"root": {
"CostAccountID": "#{body('Parse_JSON')?['root']?['CostAccountID']}",
"EndDate": "#{addSeconds('1970-01-01T00:00:00Z', div(int(body('Parse_JSON_2')?['root']?['EndDate1']),1000))}",
"StartDate": "#{addSeconds('1970-01-01T00:00:00Z', div(int(body('Parse_JSON_2')?['root']?['StartDate1']),1000))}"
}
}
RESULTS:
I have made changes to your code view. Below is the updated one
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Compose": {
"inputs": {
"root": {
"CostAccountID": "AD100",
"EndDate": "/Date(253402214400000)/",
"StartDate": "/Date(946684800000)/"
}
},
"runAfter": {},
"type": "Compose"
},
"Compose_2": {
"inputs": {
"root": {
"CostAccountID": "#{body('Parse_JSON')?['root']?['CostAccountID']}",
"EndDate1": "#{int(replace(replace(body('Parse_JSON')?['root']?['EndDate'],'/Date(',''),')/',''))}",
"StartDate1": "#{int(replace(replace(body('Parse_JSON')?['root']?['StartDate'],'/Date(',''),')/',''))}"
}
},
"runAfter": {
"Parse_JSON": [
"Succeeded"
]
},
"type": "Compose"
},
"Compose_3": {
"inputs": {
"root": {
"CostAccountID": "#{body('Parse_JSON')?['root']?['CostAccountID']}",
"EndDate": "#{addSeconds('1970-01-01T00:00:00Z', div(int(body('Parse_JSON_2')?['root']?['EndDate1']),1000))}",
"StartDate": "#{addSeconds('1970-01-01T00:00:00Z', div(int(body('Parse_JSON_2')?['root']?['StartDate1']),1000))}"
}
},
"runAfter": {
"Parse_JSON_2": [
"Succeeded"
]
},
"type": "Compose"
},
"Parse_JSON": {
"inputs": {
"content": "#outputs('Compose')",
"schema": {
"properties": {
"root": {
"properties": {
"CostAccountID": {
"type": "string"
},
"EndDate": {
"type": "string"
},
"StartDate": {
"type": "string"
}
},
"type": "object"
}
},
"type": "object"
}
},
"runAfter": {
"Compose": [
"Succeeded"
]
},
"type": "ParseJson"
},
"Parse_JSON_2": {
"inputs": {
"content": "#outputs('Compose_2')",
"schema": {
"properties": {
"root": {
"properties": {
"CostAccountID": {
"type": "string"
},
"EndDate1": {
"type": "string"
},
"StartDate1": {
"type": "string"
}
},
"type": "object"
}
},
"type": "object"
}
},
"runAfter": {
"Compose_2": [
"Succeeded"
]
},
"type": "ParseJson"
},
"Response": {
"inputs": {
"body": "#outputs('Compose_3')",
"statusCode": 200
},
"kind": "http",
"runAfter": {
"Compose_3": [
"Succeeded"
]
},
"type": "Response"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {},
"triggers": {
"manual": {
"inputs": {},
"kind": "Http",
"type": "Request"
}
}
}
}

Related

How to get a logic app to stop running after a successful run each day

I have a logic app that I want to run once a line item appears in a table each day. once that line item appear, i don't want the logic app to run anymore that day. Can't quite think of how to accomplish this.
Apart from using the related triggers you can use Terminate action to stop the flow.
After using Get entities (V2) I'm trying to Parse the result to get the timestamp of that particular entity to check if the table has an added row or not for that day
After parsing below is the condition that I'm using
{
"contains": [
"#formatDateTime(body('Parse_JSON')?[0]?['Timestamp'],'dd-MM-yyyy')",
"#formatDateTime(utcNow(),'dd-MM-yyyy')"]
}
Below is the complete flow of my Logic App
RESULTS:
To reproduce the same in your Logic App you can use the below code view
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Condition": {
"actions": {
"Terminate": {
"inputs": {
"runStatus": "Succeeded"
},
"runAfter": {},
"type": "Terminate"
}
},
"else": {
"actions": {
"Delay": {
"inputs": {
"interval": {
"count": 2,
"unit": "Hour"
}
},
"runAfter": {},
"type": "wait"
},
"HTTP": {
"inputs": {
"method": "POST",
"uri": "<URI>"
},
"runAfter": {
"Delay": [
"Succeeded"
]
},
"type": "Http"
}
}
},
"expression": {
"and": [
{
"contains": [
"#formatDateTime(body('Parse_JSON')?[0]?['Timestamp'],'dd-MM-yyyy')",
"#formatDateTime(utcNow(),'dd-MM-yyyy')"
]
}
]
},
"runAfter": {
"Parse_JSON": [
"Succeeded"
]
},
"type": "If"
},
"Get_entities_(V2)": {
"inputs": {
"host": {
"connection": {
"name": "#parameters('$connections')['azuretables']['connectionId']"
}
},
"method": "get",
"path": "/v2/storageAccounts/#{encodeURIComponent(encodeURIComponent('AccountNameFromSettings'))}/tables/#{encodeURIComponent('<TableName>')}/entities"
},
"runAfter": {},
"type": "ApiConnection"
},
"Parse_JSON": {
"inputs": {
"content": "#body('Get_entities_(V2)')?['value']",
"schema": {
"items": {
"properties": {
"FirstName": {
"type": "string"
},
"LastName": {
"type": "string"
},
"PartitionKey": {
"type": "string"
},
"RowKey": {
"type": "string"
},
"Timestamp": {
"type": "string"
},
"odata.etag": {
"type": "string"
}
},
"required": [
"odata.etag",
"PartitionKey",
"RowKey",
"Timestamp",
"FirstName",
"LastName"
],
"type": "object"
},
"type": "array"
}
},
"runAfter": {
"Get_entities_(V2)": [
"Succeeded"
]
},
"type": "ParseJson"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {
"$connections": {
"defaultValue": {},
"type": "Object"
}
},
"triggers": {
"manual": {
"inputs": {
"schema": {}
},
"kind": "Http",
"type": "Request"
}
}
},
"parameters": {
"$connections": {
"value": {
"azuretables": {
"connectionId": "/subscriptions/<SUB_ID>/resourceGroups/<RG>/providers/Microsoft.Web/connections/azuretables",
"connectionName": "azuretables",
"id": "/subscriptions/<SUB_ID>/providers/Microsoft.Web/locations/centralus/managedApis/azuretables"
}
}
}
}
}
Alternatively, you can use Recurrence trigger to trigger it in regular intervals with the same logic.

how to get a value of a json http response in azure logic app

I'm trying to get "id" value set to a variable by parsing the below output sample. The REST API call will return multiple values as shown below and I'm interested in only getting the "id" value for the particular name that users has provided/set as input in the workflow earlier either by a parameter value or by initializing a variable. How do I do this value extraction in azure logic app?
Any help much appreciated.
[
{
"id": 1,
"name": "xyz-List",
"data": {
"urls": [
"*.test1.com",
"*.test2.com"
],
"type": "exact"
},
"modify_by": "admin#xyz.com",
"modify_time": "2022-06-29T21:05:27.000Z",
"modify_type": "Created",
"pending": 0
},
{
"id": 2,
"name": "abc-List",
"data": {
"urls": [
"www.mytesting.com"
],
"type": "exact"
},
"modify_by": "admin#xyz.com",
"modify_time": "2022-06-29T21:05:27.000Z",
"modify_type": "Created",
"pending": 0
},
{
"id": 3,
"name": "azure-list",
"data": {
"type": "exact",
"urls": [
"www.xyz.com",
"www.azure-test.com"
],
"json_version": 2
},
"modify_by": "admin#xyz.com",
"modify_time": "2022-09-26T01:25:20.000Z",
"modify_type": "Edited",
"pending": 0
}
]
I have reproduced from my end and could able to make it work by parsing your REST API call value. To iterate through the Parsed JSON I have used a for-each loop and extracted the Id using the below expression and set its value to a variable.
#items('For_each')['id']
Below is the complete flow of my logic app
RESULTS:
To reproduce the same in your logic app you can use the below code view that worked for me.
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Compose": {
"inputs": [
{
"data": {
"type": "exact",
"urls": [
"*.test1.com",
"*.test2.com"
]
},
"id": 1,
"modify_by": "admin#xyz.com",
"modify_time": "2022-06-29T21:05:27.000Z",
"modify_type": "Created",
"name": "xyz-List",
"pending": 0
},
{
"data": {
"type": "exact",
"urls": [
"www.mytesting.com"
]
},
"id": 2,
"modify_by": "admin#xyz.com",
"modify_time": "2022-06-29T21:05:27.000Z",
"modify_type": "Created",
"name": "abc-List",
"pending": 0
},
{
"data": {
"json_version": 2,
"type": "exact",
"urls": [
"www.xyz.com",
"www.azure-test.com"
]
},
"id": 3,
"modify_by": "admin#xyz.com",
"modify_time": "2022-09-26T01:25:20.000Z",
"modify_type": "Edited",
"name": "azure-list",
"pending": 0
}
],
"runAfter": {
"Initialize_variable": [
"Succeeded"
]
},
"type": "Compose"
},
"For_each": {
"actions": {
"Set_variable": {
"inputs": {
"name": "Id",
"value": "#items('For_each')['id']"
},
"runAfter": {},
"type": "SetVariable"
}
},
"foreach": "#body('Parse_JSON')",
"runAfter": {
"Parse_JSON": [
"Succeeded"
]
},
"type": "Foreach"
},
"Initialize_variable": {
"inputs": {
"variables": [
{
"name": "Id",
"type": "integer"
}
]
},
"runAfter": {},
"type": "InitializeVariable"
},
"Parse_JSON": {
"inputs": {
"content": "#outputs('Compose')",
"schema": {
"items": {
"properties": {
"data": {
"properties": {
"type": {
"type": "string"
},
"urls": {
"items": {
"type": "string"
},
"type": "array"
}
},
"type": "object"
},
"id": {
"type": "integer"
},
"modify_by": {
"type": "string"
},
"modify_time": {
"type": "string"
},
"modify_type": {
"type": "string"
},
"name": {
"type": "string"
},
"pending": {
"type": "integer"
}
},
"required": [
"id",
"name",
"data",
"modify_by",
"modify_time",
"modify_type",
"pending"
],
"type": "object"
},
"type": "array"
}
},
"runAfter": {
"Compose": [
"Succeeded"
]
},
"type": "ParseJson"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {},
"triggers": {
"manual": {
"inputs": {
"schema": {}
},
"kind": "Http",
"type": "Request"
}
}
},
"parameters": {}
}
Load this into your tenant. You can use basic expressions with a condition to get your result ...
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"For_Each_Array_Item": {
"actions": {
"Condition": {
"actions": {
"Set_ID": {
"inputs": {
"name": "ID",
"value": "#item()['id']"
},
"runAfter": {},
"type": "SetVariable"
}
},
"expression": {
"and": [
{
"equals": [
"#item()['name']",
"abc-List"
]
}
]
},
"runAfter": {},
"type": "If"
}
},
"foreach": "#variables('Array Data')",
"runAfter": {
"Initialize_ID": [
"Succeeded"
]
},
"type": "Foreach"
},
"Initialize_Array_Data": {
"inputs": {
"variables": [
{
"name": "Array Data",
"type": "array",
"value": [
{
"data": {
"type": "exact",
"urls": [
"*.test1.com",
"*.test2.com"
]
},
"id": 1,
"modify_by": "admin#xyz.com",
"modify_time": "2022-06-29T21:05:27.000Z",
"modify_type": "Created",
"name": "xyz-List",
"pending": 0
},
{
"data": {
"type": "exact",
"urls": [
"www.mytesting.com"
]
},
"id": 2,
"modify_by": "admin#xyz.com",
"modify_time": "2022-06-29T21:05:27.000Z",
"modify_type": "Created",
"name": "abc-List",
"pending": 0
},
{
"data": {
"json_version": 2,
"type": "exact",
"urls": [
"www.xyz.com",
"www.azure-test.com"
]
},
"id": 3,
"modify_by": "admin#xyz.com",
"modify_time": "2022-09-26T01:25:20.000Z",
"modify_type": "Edited",
"name": "azure-list",
"pending": 0
}
]
}
]
},
"runAfter": {},
"type": "InitializeVariable"
},
"Initialize_ID": {
"inputs": {
"variables": [
{
"name": "ID",
"type": "integer"
}
]
},
"runAfter": {
"Initialize_Array_Data": [
"Succeeded"
]
},
"type": "InitializeVariable"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {
"ParameterTest1": {
"defaultValue": "\"\"",
"type": "String"
}
},
"triggers": {
"manual": {
"inputs": {
"method": "GET",
"schema": {}
},
"kind": "Http",
"type": "Request"
}
}
},
"parameters": {}
}
My example looks for the name abc-List and if it finds it, it sets the ID variable to be the associated ID of that record it found the name against.

How to monitor the creation of Blob in Azure Storage container/subfolders and Trigger a logic app to send email

We have Azure storage container with subfolders created dynamically, we want to monitor the creation of blob under this container/subfolders and trigger an email once per day with all the blobs added for the day as an attachment in the email.
What we tried is to create a Logic app with Event Grid Trigger (When a resource event occurs) like below.
we would like to know if there is way we can collect all the blobs added in a day under the container and get the contents of all those blobs and add it as an attachment and trigger an email at scheduled time once per day.
Any suggestion on
how to get all the blobs under a container, sub-folder and store the blobs metadata created as an array?
And then how to attach all the blobs created in a single email?
How to get the blob name after, "When a resource event occurs" trigger?
Based on the above requirements, we have created a logic app using timer to list & get the content of all the blob that were created on a particular day & will send an email with the content of the blob as an attachment. using the below work flow code you make the changes as per your business requirement.
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Attach": {
"inputs": {
"variables": [
{
"name": "Arraytoattach",
"type": "array"
}
]
},
"runAfter": {
"Lists_blobs_(V2)": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Blob_Name": {
"inputs": {
"variables": [
{
"name": "Count",
"type": "integer",
"value": "#length(variables('Arraytoattach'))"
}
]
},
"runAfter": {
"For_each": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"For_each": {
"actions": {
"Compose_2": {
"inputs": "#items('For_each')?['LastModified']",
"runAfter": {},
"type": "Compose"
},
"Compose_3": {
"inputs": "#formatDateTime(outputs('Compose_2'),'yyyy-MM-dd')",
"runAfter": {
"Compose_2": [
"Succeeded"
]
},
"type": "Compose"
},
"Condition": {
"actions": {
"Append_to_array_variable": {
"inputs": {
"name": "Arraytoattach",
"value": {
"ContentBytes": "#body('Get_blob_content_(V2)_2')?['$content']",
"Name": "#items('For_each')?['Name']"
}
},
"runAfter": {
"Get_blob_content_(V2)_2": [
"Succeeded"
]
},
"type": "AppendToArrayVariable"
},
"Get_blob_content_(V2)_2": {
"inputs": {
"host": {
"connection": {
"name": "#parameters('$connections')['azureblob']['connectionId']"
}
},
"method": "get",
"path": "/v2/datasets/#{encodeURIComponent(encodeURIComponent('stacklogictest'))}/files/#{encodeURIComponent(encodeURIComponent(items('For_each')?['Path']))}/content",
"queries": {
"inferContentType": true
}
},
"runAfter": {},
"type": "ApiConnection"
}
},
"expression": {
"and": [
{
"equals": [
"#outputs('Compose_3')",
"#formatDateTime(utcNow(),'yyyy-MM-dd')"
]
}
]
},
"runAfter": {
"Compose_3": [
"Succeeded"
]
},
"type": "If"
}
},
"foreach": "#body('Lists_blobs_(V2)')?['value']",
"runAfter": {
"Attach": [
"Succeeded"
]
},
"type": "Foreach"
},
"Lists_blobs_(V2)": {
"inputs": {
"host": {
"connection": {
"name": "#parameters('$connections')['azureblob']['connectionId']"
}
},
"method": "get",
"path": "/v2/datasets/#{encodeURIComponent(encodeURIComponent('stacklogictest'))}/foldersV2/#{encodeURIComponent(encodeURIComponent('JTJmdGVzdDEyMw=='))}",
"queries": {
"nextPageMarker": "",
"useFlatListing": false
}
},
"metadata": {
"JTJmdGVzdDEyMw==": "/test123"
},
"runAfter": {},
"type": "ApiConnection"
},
"Send_an_email_(V2)": {
"inputs": {
"body": {
"Attachments": "#variables('Arraytoattach')",
"Body": "<p>Total Number of blob created today : #{variables('Count')}</p>",
"Subject": "Blob created Today",
"To": "<**ReciepientMailAddress**>"
},
"host": {
"connection": {
"name": "#parameters('$connections')['office365']['connectionId']"
}
},
"method": "post",
"path": "/v2/Mail"
},
"runAfter": {
"Blob_Name": [
"Succeeded"
]
},
"type": "ApiConnection"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {
"$connections": {
"defaultValue": {},
"type": "Object"
}
},
"triggers": {
"Recurrence": {
"recurrence": {
"frequency": "Day",
"interval": 1,
"startTime": "2021-07-15T04:00:00Z"
},
"type": "Recurrence"
}
}
},
"parameters": {
"$connections": {
"value": {
"azureblob": {
"connectionId": "/subscriptions/<subscriptionId>/resourceGroups/<resourceGroups>/providers/Microsoft.Web/connections/azureblob",
"connectionName": "azureblob",
"id": "/subscriptions/<subscriptionId>/providers/Microsoft.Web/locations/southindia/managedApis/azureblob"
},
"office365": {
"connectionId": "/subscriptions/<subscriptionId>/resourceGroups/<resourceGroups>/providers/Microsoft.Web/connections/office365",
"connectionName": "office365",
"id": "/subscriptions/<subscriptionId>/providers/Microsoft.Web/locations/southindia/managedApis/office365"
}
}
}
}
}
how to get all the blobs under a container, sub-folder and store the blobs metadata created as an array?
Ans: Using the Event Grid you can add all the blob under a particular container to a single array because event grid triggers the logic app when a new blob is added.
And then how to attach all the blobs created in a single email?
Ans: Due to outlook restrictions, we cannot sent or attach the data which excceds more than 25 MB.
3.How to get the blob name after, "When a resource event occurs" trigger?
Ans : As shown in the below image initialize a string variable and add it to the next of event grid event and add the below experssion to get the blob name from the event grid output
first(split(last(split(string(triggerBody()),'/blobs/')),'","event'))
The above logic app will fail if the content type of the blob is text you need make the changes accordingly based on requirement.
Here is the sample output of the above logic app
Created a logic app to send email with attachment of all the blobs inside a container that were added a day before the current day.
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Current_time": {
"inputs": {},
"kind": "CurrentTime",
"runAfter": {
"Lists_blobs_(V2)": [
"Succeeded"
]
},
"type": "Expression"
},
"For_each": {
"actions": {
"For_each_2": {
"actions": {
"Condition": {
"actions": {
"Append_to_array_variable": {
"inputs": {
"name": "attachements",
"value": "#outputs('Compose')"
},
"runAfter": {
"Compose": [
"Succeeded"
]
},
"type": "AppendToArrayVariable"
},
"Compose": {
"inputs": {
"ContentBytes": "#{base64(body('Get_Blob'))}",
"Name": "#{last(split(items('For_each_2')?['Path'],'/'))}"
},
"runAfter": {
"Get_Blob": [
"Succeeded"
]
},
"type": "Compose"
},
"Get_Blob": {
"inputs": {
"host": {
"connection": {
"name": "#parameters('$connections')['azureblob']['connectionId']"
}
},
"method": "get",
"path": "/v2/datasets/#{encodeURIComponent(encodeURIComponent('<StorageAccountName/connection>'))}/files/#{encodeURIComponent(encodeURIComponent(items('For_each_2')?['Path']))}/content",
"queries": {
"inferContentType": true
}
},
"runAfter": {},
"type": "ApiConnection"
}
},
"expression": {
"and": [
{
"greater": [
"#items('For_each_2')?['LastModified']",
"#addDays(body('Current_time'),-1)"
]
}
]
},
"runAfter": {},
"type": "If"
}
},
"foreach": "#body('Lists_blobs_(V2)_3')?['value']",
"runAfter": {
"Lists_blobs_(V2)_3": [
"Succeeded"
]
},
"type": "Foreach"
},
"Lists_blobs_(V2)_3": {
"inputs": {
"host": {
"connection": {
"name": "#parameters('$connections')['azureblob']['connectionId']"
}
},
"method": "get",
"path": "/v2/datasets/#{encodeURIComponent(encodeURIComponent('<storageaccount connection>'))}/foldersV2/#{encodeURIComponent(encodeURIComponent(items('For_each')?['Path']))}",
"queries": {
"nextPageMarker": "",
"useFlatListing": false
}
},
"runAfter": {},
"type": "ApiConnection"
}
},
"foreach": "#body('Lists_blobs_(V2)')?['value']",
"runAfter": {
"Current_time": [
"Succeeded"
]
},
"type": "Foreach"
},
"Initialize_variable": {
"inputs": {
"variables": [
{
"name": "attachements",
"type": "array"
}
]
},
"runAfter": {},
"type": "InitializeVariable"
},
"Lists_blobs_(V2)": {
"inputs": {
"host": {
"connection": {
"name": "#parameters('$connections')['azureblob']['connectionId']"
}
},
"method": "get",
"path": "/v2/datasets/#{encodeURIComponent(encodeURIComponent('<storageaccount connection>'))}/foldersV2/#{encodeURIComponent(encodeURIComponent('JTJmY2FyYm9uYmxh='))}",
"queries": {
"nextPageMarker": "",
"useFlatListing": false
}
},
"metadata": {
"JTJmY2FyYm9uYmxh=": "/<containerName>"
},
"runAfter": {
"Initialize_variable": [
"Succeeded"
]
},
"type": "ApiConnection"
},
"Send_an_email_(V2)_3": {
"inputs": {
"body": {
"Attachments": "#variables('attachements')",
"Body": "<p>body</p>",
"Subject": "Subject",
"To": "Email"
},
"host": {
"connection": {
"name": "#parameters('$connections')['office365']['connectionId']"
}
},
"method": "post",
"path": "/v2/Mail"
},
"runAfter": {
"For_each": [
"Succeeded",
"Failed",
"Skipped",
"TimedOut"
]
},
"type": "ApiConnection"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {
"$connections": {
"defaultValue": {},
"type": "Object"
}
},
"triggers": {
"Recurrence": {
"recurrence": {
"frequency": "Day",
"interval": 1,
"schedule": {
"hours": [
"9"
],
"minutes": [
0
]
},
"timeZone": "Standard Time"
},
"type": "Recurrence"
}
}
},
"parameters": {
"$connections": {
"value": {
"azureblob": {
"connectionId": "/subscriptions/<subscriptionId>/resourceGroups/<ResourceGroup>/providers/Microsoft.Web/connections/azureblob",
"connectionName": "azureblob",
"id": "/subscriptions/<subscriptionId>/providers/Microsoft.Web/locations/<location>/managedApis/azureblob"
},
"office365": {
"connectionId": "/subscriptions/<subscriptionId>/resourceGroups/<ResourceGroup>/providers/Microsoft.Web/connections/office365-1",
"connectionName": "office365",
"id": "/subscriptions/subscriptionId>/providers/Microsoft.Web/locations/<location>/managedApis/office365"
}
}
}
}
}

Azure LogicApps: Conversion from String to Float returns zero

I am surprised to see this, but I witness that in some instance the string value aren't converting as expected to float; mostly returns zero.
The following image shows what happens. As you see I have 2 variables namely var_MarginStr of type string and var_MarginValues of type float in my Logic App. I am assigning var_MarginVal as follows:
var_MarginVal = float(string(variables('var_MarginStr')))
In my working where I trigger my logic app after a new blob is inserted into a blob storage account. The content(*.csv) of the blob is passed to an Azure Function which returns a JSON object. The JSON object is then being looped over each item and is sent to my DB via a Stored Proc.
I have checked my Azure Function which converts the content to JSON working perfectly and the response from such is:
{
"fileName": "20200307-PLC-JKB-Margin.csv",
"agentName": "PLC",
"noOfRecords": 5,
"data": [
{
"accountId": "JKB1234LC",
"marginValue": "0.00"
},
{
"accountId": "JKB4321LC",
"marginValue": "1200000.00"
},
{
"accountId": "JKB5678LC",
"marginValue": "6000000.00"
},
{
"accountId": "JKB8765LC",
"marginValue": "4000000.00"
},
{
"accountId": "JKB9123LC",
"marginValue": "0.00"
}
]
}
Here is my entire LogicApp:
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"CSVTOJSON": {
"inputs": {
"body": "#body('Get_blob_content')",
"function": {
"id": "/subscriptions/xxxx/resourceGroups/xxxx-PRD-PORTAL-01/providers/Microsoft.Web/sites/jksbmarginrequest/functions/CSVTOJSON"
},
"method": "POST",
"queries": {
"fileName": "#triggerBody()?['Name']"
}
},
"runAfter": {
"[Initialize]_For_Composed_AccountId": [
"Succeeded"
]
},
"type": "Function"
},
"Condition": {
"actions": {
"Apply_to_DB": {
"actions": {
"Execute_stored_procedure_(V2)": {
"inputs": {
"body": {
"pActualAccountId": "#{items('Apply_to_DB')?['accountId']}#{variables('var_ComposeAccountIdSuffix')}",
"pAgentId": "#variables('var_AgentName')",
"pEffectiveDate": "#{formatDateTime(utcNow(),'yyyy-MM-dd')}",
"pMarginVal": "#variables('var_MarginVal')"
},
"host": {
"connection": {
"name": "#parameters('$connections')['sql']['connectionId']"
}
},
"method": "post",
"path": "/v2/datasets/#{encodeURIComponent(encodeURIComponent('default'))},#{encodeURIComponent(encodeURIComponent('default'))}/procedures/#{encodeURIComponent(encodeURIComponent('[dbo].[usp_MarginAddUpdate]'))}"
},
"runAfter": {
"[Set]_Margin_Value_Float": [
"Succeeded"
]
},
"type": "ApiConnection"
},
"[Set]_Margin_Value_Float": {
"inputs": {
"name": "var_MarginVal",
"value": "#float(string(variables('var_MarginStr')))"
},
"runAfter": {
"[Set]_Margin_Value_String": [
"Succeeded"
]
},
"type": "SetVariable"
},
"[Set]_Margin_Value_String": {
"inputs": {
"name": "var_MarginStr",
"value": "#items('Apply_to_DB')?['marginValue']"
},
"runAfter": {},
"type": "SetVariable"
}
},
"foreach": "#body('Parse_JSON')?['data']",
"runAfter": {
"For_each": [
"Succeeded"
]
},
"type": "Foreach"
},
"Create_HTML_table": {
"inputs": {
"format": "HTML",
"from": "#body('Parse_JSON')?['data']"
},
"runAfter": {
"Apply_to_DB": [
"Succeeded"
]
},
"type": "Table"
},
"Execute_a_SQL_query_(V2)": {
"inputs": {
"body": {
"actualParameters": {
"pAgentId": "#variables('var_AgentName')"
},
"formalParameters": {
"pAgentId": "VARCHAR(10)"
},
"query": "select * from [dbo].[Parser_MarginFileSettings]\nWhere AgentId =#pAgentId"
},
"host": {
"connection": {
"name": "#parameters('$connections')['sql']['connectionId']"
}
},
"method": "post",
"path": "/v2/datasets/#{encodeURIComponent(encodeURIComponent('default'))},#{encodeURIComponent(encodeURIComponent('default'))}/query/sql"
},
"runAfter": {
"[Set]_Agent_Name": [
"Succeeded"
]
},
"type": "ApiConnection"
},
"For_each": {
"actions": {
"[Set]_Composed_Account_ID_with_Suffix": {
"inputs": {
"name": "var_ComposeAccountIdSuffix",
"value": "#items('For_each')?['Suffix_AccountId']"
},
"runAfter": {},
"type": "SetVariable"
}
},
"foreach": "#body('Execute_a_SQL_query_(V2)')?['resultsets']?['Table1']",
"runAfter": {
"Execute_a_SQL_query_(V2)": [
"Succeeded"
]
},
"type": "Foreach"
},
"Parse_JSON": {
"inputs": {
"content": "#body('CSVTOJSON')",
"schema": {
"properties": {
"agentName": {
"type": "string"
},
"data": {
"items": {
"properties": {
"accountId": {
"type": "string"
},
"marginValue": {
"type": "string"
}
},
"required": [
"accountId",
"marginValue"
],
"type": "object"
},
"type": "array"
},
"fileName": {
"type": "string"
},
"noOfRecords": {
"type": "integer"
}
},
"type": "object"
}
},
"runAfter": {},
"type": "ParseJson"
},
"[Set]_Agent_Name": {
"inputs": {
"name": "var_AgentName",
"value": "#body('Parse_JSON')?['agentName']"
},
"runAfter": {
"Parse_JSON": [
"Succeeded"
]
},
"type": "SetVariable"
}
},
"else": {
"actions": {
"Compose_Fail-over_Data": {
"inputs": {
"File_Name": "#triggerBody()?['Name']",
"Message": "#body('CSVTOJSON')",
"Status_Code": "#outputs('CSVTOJSON')['statusCode']"
},
"runAfter": {},
"type": "Compose"
},
"For_Error_Listing": {
"inputs": {
"format": "HTML",
"from": "#outputs('Compose_Fail-over_Data')"
},
"runAfter": {
"Compose_Fail-over_Data": [
"Succeeded"
]
},
"type": "Table"
},
"Send_an_email_(V2)": {
"inputs": {
"body": {
"Body": "<p><u><strong>An Error Occured While Updating Margin Request File<br>\n<br>\n</strong></u><u><strong>#{outputs('Compose_Fail-over_Data')}</strong></u><u><strong></strong></u><br>\n</p>",
"Subject": "Margin File Output",
"To": "itops#jkstock.keells.com"
},
"host": {
"connection": {
"name": "#parameters('$connections')['office365']['connectionId']"
}
},
"method": "post",
"path": "/v2/Mail"
},
"runAfter": {
"For_Error_Listing": [
"Succeeded"
]
},
"type": "ApiConnection"
}
}
},
"expression": {
"and": [
{
"equals": [
"#outputs('CSVTOJSON')['statusCode']",
200
]
}
]
},
"runAfter": {
"CSVTOJSON": [
"Succeeded"
]
},
"type": "If"
},
"Get_blob_content": {
"inputs": {
"host": {
"connection": {
"name": "#parameters('$connections')['azureblob']['connectionId']"
}
},
"method": "get",
"path": "/datasets/default/files/#{encodeURIComponent(encodeURIComponent(triggerBody()?['Path']))}/content",
"queries": {
"inferContentType": true
}
},
"runAfter": {},
"runtimeConfiguration": {
"staticResult": {
"name": "Get_blob_content0",
"staticResultOptions": "Disabled"
}
},
"type": "ApiConnection"
},
"[Initialize]_Agent_Name": {
"inputs": {
"variables": [
{
"name": "var_AgentName",
"type": "string",
"value": "PLC"
}
]
},
"runAfter": {
"Get_blob_content": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"[Initialize]_For_Composed_AccountId": {
"inputs": {
"variables": [
{
"name": "var_ComposeAccountIdSuffix",
"type": "string"
}
]
},
"runAfter": {
"[Initialize]_For_Margin_Value_FLoat": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"[Initialize]_For_Margin_Value_FLoat": {
"inputs": {
"variables": [
{
"name": "var_MarginVal",
"type": "float",
"value": 0
}
]
},
"runAfter": {
"[Initialize]_Margin_Value_String": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"[Initialize]_Margin_Value_String": {
"inputs": {
"variables": [
{
"name": "var_MarginStr",
"type": "string"
}
]
},
"runAfter": {
"[Initialize]_Agent_Name": [
"Succeeded"
]
},
"type": "InitializeVariable"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {
"$connections": {
"defaultValue": {},
"type": "Object"
}
},
"staticResults": {
"Get_blob_content0": {
"outputs": {
"headers": {},
"statusCode": "OK"
},
"status": "Succeeded"
}
},
"triggers": {
"When_a_blob_is_added_or_modified_(properties_only)": {
"inputs": {
"host": {
"connection": {
"name": "#parameters('$connections')['azureblob']['connectionId']"
}
},
"method": "get",
"path": "/datasets/default/triggers/batch/onupdatedfile",
"queries": {
"folderId": "JTJmcGxj",
"maxFileCount": 1
}
},
"metadata": {
"JTJmcGxj": "/plc"
},
"recurrence": {
"frequency": "Second",
"interval": 3
},
"splitOn": "#triggerBody()",
"type": "ApiConnection"
}
}
},
"parameters": {
"$connections": {
"value": {
"azureblob": {
"connectionId": "/subscriptions/xxxx/resourceGroups/xxx-PRD-PORTAL-01/providers/Microsoft.Web/connections/azureblob-2",
"connectionName": "azureblob-2",
"id": "/subscriptions/xxxx/providers/Microsoft.Web/locations/southeastasia/managedApis/azureblob"
},
"office365": {
"connectionId": "/subscriptions/xxxx/resourceGroups/xxx-PRD-PORTAL-01/providers/Microsoft.Web/connections/office365",
"connectionName": "office365",
"id": "/subscriptions/xxxx/providers/Microsoft.Web/locations/southeastasia/managedApis/office365"
},
"sql": {
"connectionId": "/subscriptions/xxxx/resourceGroups/xxx-PRD-PORTAL-01/providers/Microsoft.Web/connections/sql-6",
"connectionName": "sql-6",
"id": "/subscriptions/xxxx/providers/Microsoft.Web/locations/southeastasia/managedApis/sql"
}
}
}
}
}
When a For Each runs by default it runs iterations concurrently. The variables are not guaranteed to use the value for the current iteration. If you change the For Each to run sequentially it will work with the variables. In the For Each settings turn on Concurrency Control and set the Degree of Parallelism to 1. The other option is to remove the use of variables in the loop if you want it to run in parallel.
The Microsoft documentation for loop on this page https://learn.microsoft.com/en-us/azure/logic-apps/logic-apps-control-flow-loops says
To get predictable results from operations on variables during each
loop iteration, run those loops sequentially. For example, when a
concurrently running loop ends, the increment, decrement, and append
to variable operations return predictable results. However, during
each iteration in the concurrently running loop, these operations
might return unpredictable results.

Unable to set value to variable it always take initial value in logic app

I have one variable I set a default value as 0.
In for_each I'm setting new value to startIndex variable and use that variable in For_each but still it is using old 0 value.
logic app code -
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"For_each_2": {
"actions": {
"Set_variable_3": {
"inputs": {
"name": "output",
"value": "#{split(items('For_each_2'),':')[0]}:#{substring(variables('mydata'),variables('startindex'),int(split(items('For_each_2'),':')[1]))}"
},
"runAfter": {},
"type": "SetVariable"
},
"Set_variable_4": {
"inputs": {
"name": "startIndex",
"value": "#int(split(items('For_each_2'),':')[1])"
},
"runAfter": {
"Set_variable_3": [
"Succeeded"
]
},
"type": "SetVariable"
}
},
"foreach": "#variables('splitvar')",
"runAfter": {
"Initialize_variable_9": [
"Succeeded"
]
},
"type": "Foreach"
},
"Initialize_variable_5": {
"inputs": {
"variables": [
{
"name": "mydata",
"type": "String",
"value": "abcdefg"
}
]
},
"runAfter": {},
"type": "InitializeVariable"
},
"Initialize_variable_6": {
"inputs": {
"variables": [
{
"name": "key",
"type": "String",
"value": "AA:3;BB:2"
}
]
},
"runAfter": {
"Initialize_variable_5": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Initialize_variable_7": {
"inputs": {
"variables": [
{
"name": "splitvar",
"type": "Array",
"value": "#split(variables('key'),';')"
}
]
},
"runAfter": {
"Initialize_variable_6": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Initialize_variable_8": {
"inputs": {
"variables": [
{
"name": "output",
"type": "String"
}
]
},
"runAfter": {
"Initialize_variable_7": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Initialize_variable_9": {
"inputs": {
"variables": [
{
"name": "startIndex",
"type": "Integer",
"value": 0
}
]
},
"runAfter": {
"Initialize_variable_8": [
"Succeeded"
]
},
"type": "InitializeVariable"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {},
"triggers": {
"manual": {
"inputs": {
"schema": {}
},
"kind": "Http",
"type": "Request"
}
}
}
}
You need to enable concurrency control on the for each action. As default the for each action run with a Degree of Parallelism set to 20. So it runs the action 20 times in parallel as the default behavior. Turn it down to 1.
]2

Resources