Logic Apps: How to add several actions inside a Loop (or foreach actions)

You can download the entire article as a PDF document.
Logic Apps: How to add several actions inside a Loop (or foreach actions)

Following my latest posts where I talked about the new “The ability to call nested Logic Apps directly from Logic Apps Designer”. Let’s look how a nested Logic App can help us overcome the current Logic Apps limitation regarding for each’ operations, in special, the ability to add more than one action inside the loop;

Using/Implementing Looping inside Logic Apps

If you are used to working with BizTalk Server, we have certain shapes and behaviors inside BizTalk Orchestrations that we would love to have in Logic Apps, at a first glimpse, we may be surprised the lack of features/shapes to perform certain operations…however, that doesn’t mean that they are missing, most of the times we still can do those things… but in a different manner, so we may need to look the “problem” from another angle.

Looping is one of those things!

We don’t have any Looping shape, action or operation that we can use in the Logic App Designer, similar to what we have with Conditions.

01-Logic-Apps-Conditions-shape

In the previous designer (v1) we had an option in the connectors, “Repeat over the list“, that allowed us to iterate over an array of items and run an action for each item in that list.

The current design doesn’t have any more this option, but again that doesn’t mean that you can’t. In this new Logic App version or designer, if it detects that the input from the previous action or trigger it’s an array, and if you try to use this input in a subsequent action, it will, almost every time, automatically put you on a for each operation. Which means that you are running this action for each item in that list.

Let’s look, and use, the basic scenario that we are using in the last posts, were:

  • The Logic Apps is trigger by a new tweet containing the hashtag we are listening;
  • And then create a file;

For now, let’s ignore the dynamic creation of the file name using Azure Functions. So we have this basic Logic App

02-Logic-Apps-Looping-no-loop-Basic-flow

Because each tweet will generate a new execution of this Logic App, the trigger input will be a simple single message and not an array. If we switch to code view we will see that the Create file action will only be executed once and it’s not inside of any loop operation.

03-Logic-Apps-Looping-no-loop-Basic-flow-code-view

So let’s make some changes!

We will use a similar scenario, but this time we want that our Logic App:

  • To be triggered every hour;
  • Retrieve the last 20 tweets with the hashtag #LogicApp
  • And then create a file for each tweet in our Dropbox

For that, we will create a new Logic App called “LoopingInsideLogicApps

  • Add a “Recurrence” trigger, and set the:
    • Frequency” property to “Hour
    • And the “Interval” property to “1

04-Logic-Apps-Looping-Reccurence-Trigger

  • Select the plus sign, and then choose “Add an action
  • From the search box select “Show Microsoft managed APIs”, type “twitter” and select the “Twitter – Search tweet” action
    • Set the “Query text” property with “#LogicApps” hashtag
    • You can expand the action to see all the properties if you click “” in the lower left corner
    • And see and define the number of results you want to return

05-Logic-Apps-Looping-Search-For-Tweets

  • Select the plus sign, and then choose “Add an action
  • From the search box select “Show Microsoft managed APIs”, type “Dropbox” and select the “Dropbox – Create file” action
    • Set the “Folder path” property, let’s say the root by typing: /
    • On the “File name” property, set the parameter “Tweet id” from the output of “Search tweet” action as input, following by the string “.txt”
    • On the “File Content” property, set the parameter “Tweet text” from the output of “Search tweet” action as input

06-Logic-Apps-Looping-For-each-Tweets-Create-File

If we “Save” our Logic Apps we will notice that 20 new files will be created in our Dropbox without us having defined any parameter or configuration inside the actions that would tell it to iterate over a list/array.

07-Logic-Apps-Looping-For-each-Tweets-Create-File-dropbox

This happened because the designer “was smart” to understand that in input from the “Search Tweet” action is an array and automatically told the “Create file” action to work inside a for each so that it could iterate over all the items in the array.

Trying to add several actions inside a for each

Let’s say now that we want to call our Azure Function to generate the file name and create the file name in our Dropbox with it.

At first glance, we might say that:

  • After the “Twitter – Search tweet” action, we need to call our Azure Function: “CreateFileName”, because it doesn’t need inputs we set the input as an empty JSON message
  • And reconfigure the “Dropbox – Create file” action in order that the “File name” property is set with the “Filename” parameter from the output of “CreateFileName” function as input

08-Logic-Apps-Looping-For-each-Tweets-several-actions

If we once again, “Save” our Logic Apps and this time, execute it manually to for it to run. You will notice that:

  • The CreateFileName function is successfully executed;
  • But the Create file action failed. If you see the output, you will notice that the first file was created successfully but the following one’s got the following error:

File ‘/NewTweet_6785b86d-4dda-4119-968f-c189416f22bc.txt’ already exists. Use the Update operation to update an existing file.

09-Logic-Apps-Looping-For-each-Tweets-several-actions-create-dropbox-files-error

Maintaining in the run history, but selecting the “CreateFileName” action to see what was the output of the function we will notice that it was a simple output:

{    
    "statusCode": 200,    
    "headers": {    
        "pragma": "no-cache",    
        "cache-Control": "no-cache",    
        "date": "Wed, 20 Apr 2016 15:01:18 GMT",    
        "set-Cookie": "ARRAffinity=9b8e91fd330bc5b8e4bdd3e129b0412d5daca54f6c2ff8a25f773cd80fad03aa;
 Path=/; Domain=functionssandromsdn.azurewebsites.net",    
        "server": "Microsoft-IIS/8.0",    
        "x-AspNet-Version": "4.0.30319",    
        "x-Powered-By": "ASP.NET"    
    },    
    "body": {    
        "FileName": "NewTweet_6785b86d-4dda-4119-968f-c189416f22bc.txt"    
    }    
}

If we go back to our Logic App designer and switch to “Code View” we will notice why this happened. By setting the input of our function with and empty JSON message were are not telling to the Logic App to iterate over the output array from the “Search Tweet” action and call the function to generate a different file name for each item.

Instead, if we analyze the code we will see that the “CreateFileName” function is only called one time, and we will send to the connector Dropbox this same value to all the tweets

10-Logic-Apps-Looping-For-each-Tweets-several-actions-create-dropbox-files-error-why

Trying to add several actions inside a for each (second shoot)

Ok, that didn’t work well. So what if we try to force the call to the Azure Function to be inside the for each statement?

Let’s them make some changes to our Logic App flow:

  • First, delete the “File Name” property from the “Dropbox – Create file” action
    • Leave it empty
  • Second, let’s send a dummy JSON message to our Azure Function, forcing this action to iterate over the “Search tweet” output array of items by setting the following JSON message:
{ "dummy": ['Tweet text'] }

11-Logic-Apps-Looping-CreateFileName-Dummy-Msg

If we switch to “Code view” you will notice that now this action is under a for each:

"foreach": "@body('Search_tweet')"

12-Logic-Apps-Looping-CreateFileName-Dummy-Msg-code

The problem of this approach is that

  • CreateFileName” action
  • And “Dropbox – Create file” action

Are in two different for each’ statements and if we try to use both in the same action, for example trying to set the “Body” parameter from the output “CreateFileName” function we will receive the following error:

13-Logic-Apps-Looping-CreateFileName-Design-error

Basic workaround to solve this problem

So, one of the workarounds that you have is to modify your Azure Function, or create a new one to be able to receive one parameter:

  • the twitter message

and return two parameters:

  • The filename generated
  • And the twitter message that was passed as an input

For example:

module.exports = function (context, data) { 
        
  var Tweet = data.Tweet; 
  var d = new Date().getTime(); 
  var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { 
        var r = (d + Math.random()*16)%16 | 0; 
        d = Math.floor(d/16); 
        return (c=='x' ? r : (r&0x3|0x8)).toString(16); 
  }); 
        
  // Response of the function to be used later. 
  context.res = { 
    body: { 
      Msg: Tweet.text, 
      FileName: 'TweetMsg_' + uuid + ".txt" 
    } 
  }; 
  context.done();            
};

If we are using this strategy, we then need to configure the input of the function as:

{ "Text": ['Tweet text'] }

14-Logic-Apps-Looping-CreateFileName-with-input-Msg

This will iterate over the list of tweets and will create another list containing all the information that we need to send to the Dropbox connector.

We then need to change all the parameters of the “Dropbox – Create file” action and instead of configuring with values from the “Search tweet” action that will force it to iterate, we will bind it to the output provide by the Azure function output

15-Logic-Apps-Looping-Dropbox-with-CreateFileName-values

This will tell to this action to iterate over the function output array to create all the files in Dropbox.

16-Logic-Apps-Looping-Dropbox-with-CreateFileName-values-code

Once again, if we “Save” our Logic App and run it, we will see that now everything will work fine.

However, in this basic workaround we are not adding several actions to a for each statement, instead, we are avoiding, going around it and duplicate the content in another list/array… but it’s there another way?

How to add several actions inside a for each

Indeed, there is a better way to accomplish that, and the solution is to call another Logic App (at least while we do not have this functionality in the design).

Still remember our Logic App that we create in my previous posts called “AddFileToDropbox” that:

  • Its trigger manually, which means through an HTTP post, allowing to be invoked by other Logic Apps
  • Then it will call an Azure Function to dynamically generate a filename;
  • Create a Dropbox file
  • The filename it’s provided by the Azure Function;
  • And the content of the message it’s passed in the HTTP request that triggers this Logic App.
  • And finally return an HTTP response based on the status of the file creation

We will reuse this “child” Logic App in this demo now.

So what we need to do now is delete the last two action from our current Logic App:

  • “Dropbox – Create file” action
  • And call “CreateFileName” function action

And then call our “child” Logic App “AddFileToDropbox”. To accomplish that we need:

  • Select the plus sign, and then choose “Add an action
  • When you select “Add an Action”, the search box will be presented where all the available actions. But now, on the search box, you can select the option: “Show Logic Apps in the same region
    • And then select “AddFileToDropbox
    • On the “Text” property we need to set the parameter “Tweet text” from the output of “Search tweet” action as input

17-Logic-Apps-Looping-Call-Logic-app-to-add-multiple-actions

If we now “Save” our Logic App and run it manually, we instantly see that:

  • the “Search tweet” action was successfully executed
  • and the “AddFileToDropbox” action is being executed

18-Logic-Apps-Looping-Call-Logic-app-to-add-multiple-actions-executions

We can go to our “child” Logic App to see its runs (the historic) and you probably see that some of them are already finished and others are still running

19-Logic-Apps-Looping-Call-Logic-app-to-add-multiple-actions-executions-child

Once all the child runs caused by the action of the parent are finished, the parent Logic App will receive the knowledge and will terminate successfully also (if all the runs finish successfully)

How is the behavior of calling a nested Logic App inside a for each statement?

You may ask yourself how that works, it will execute on iteration one by one, in other words, in other words, will it call the child Logic App synchronously and wait for it to finish returning the response to call another one? Or it will be asynchronous?

Well in BizTalk terms it would be like using a Parallel Actions shape, where all the actions will be executed concurrently but independently but the parent Logic App processing does not continue until all have completed. The parent Logic App, in this case, will receive an array containing all the responses of the child executions.

You can download the entire article as a PDF document.
Logic Apps: How to add several actions inside a Loop (or foreach actions)
Author: Sandro Pereira

Sandro Pereira lives in Portugal and works as a consultant at DevScope. In the past years, he has been working on implementing Integration scenarios both on-premises and cloud for various clients, each with different scenarios from a technical point of view, size, and criticality, using Microsoft Azure, Microsoft BizTalk Server and different technologies like AS2, EDI, RosettaNet, SAP, TIBCO etc. He is a regular blogger, international speaker, and technical reviewer of several BizTalk books all focused on Integration. He is also the author of the book “BizTalk Mapping Patterns & Best Practices”. He has been awarded MVP since 2011 for his contributions to the integration community.

  • svk vinoth

    Hi team,
    I need help for logic app…how to use break condition in for each loop using logic app designer.(inside the for each loop i’m going to use IF condition once IF condition succeed then have to exit the loop at the time )…
    please advise me…

One Platform Operations, Monitoring and Analytics Software
BizTalk360

microsoft biztalk

Learn more

Over 500 customers across 30+ countries depend on BizTalk360

ServiceBus360

Azure service bus

Learn more

Start managing your Azure Service Bus namespaces in minutes

One Platform - Operations, Monitoring and Analytics Software
BizTalk360

microsoft biztalk

Learn more

Over 500 customers across 30+ countries depend on BizTalk360

One Platform - Operations, Monitoring and Analytics Software
ServiceBus360

Azure service bus

Learn more

Start managing your Azure Service Bus namespaces in minutes

Back to Top