One of the questions I saw on Twitter after yesterday's Azure App Service launch was: how do you do an if-then-else in a Logic App? Or even a For loop?
If you're coming from a BizTalk Orchestration or Windows Workflow background, you may be surprised by the lack of shapes in a Logic App for performing these operations.
However, you can still do all those things: you just need to look at the problem differently.
A Logic App is just a JSON file that contains a list of Triggers (apps that can start the flow) and Actions (apps that are executed as part of the flow).
You can see the JSON file by clicking the Code View button (at the top of the screen whilst you're editing a logic app - you'll need to have saved your logic app first).
[In another post I'll go through the format of this JSON file - you can actually author Logic Apps in Notepad, and then upload them to Azure, or paste them into the designer.]
API Apps are just a web site hosted on an IIS server (there's bit more to it than that, but we won't go into that today). They have an exposed REST API (hence the name API Apps) and you interact with the using standard HTTP verbs e.g. POST, GET, PUT, and DELETE.
Therefore, for a logic app to make use of an API App, it needs to know the endpoint for the API App. You can see this if you look at the JSON code for your logic app.
Take the example where you've added a BizTalk File Connector as the trigger for your Logic App. The File Connector will poll for the presence of a file on a remote (on-prem usually) server.
The config for this in the JSON file looks like this:
"id": "/subscriptions/(sub id)/resourcegroups/(resourcegroup name)/providers/Microsoft.AppService/apiapps/fileconnector",
"triggerState": "@coalesce(triggers()?.outputs?.body?['triggerState'], '')",
If you look at the above, you can see the URI to the FileConnector API App in the inputs section, under host then id.
It's this JSON file that will store the execute conditions and repeat conditions that we use to control conditional statements and looping.
How to do conditional statements
By default, all actions in a logic app run in parallel: the logic app needs to be triggered in some way (either by being called directly, or via a trigger API App), but once running, the logic app will run all contained API Apps in parallel. Unless you tell it not to.
Those of you who watched Josh Twist and Scott Hanselman's video on creating Logic Apps may have noted that Scott pointed out that you chain API Apps in a Logic Flow together like in a pipeline and have data stream between them - and this is the crucial point: Each API App can have a set of conditions that indicate when it should execute. The API App is only executed (called) when these conditions evaluate to true.
These conditions are used for 2 purposes:
- To chain API Apps together e.g. only run the second API App once the first has generated some output.
- To provide conditional operations: only execute this API App if this condition is true.
Now, to most BizTalk and Workflow developers, this may seem like an odd way to do it - unlike an Orchestration or Workflow, you can't look at a flow and see immediately what the conditions are. But this will come over time (fingers crossed - this is just a public preview remember - Microsoft want all the feedback they can get). In the meantime, to set conditions:
- On any API App in a logic flow, select the gear icon in the top right of the app.
- Select "Add a condition to be met" from the menu:
- In the Text Box that appears, type in a logic app formula to be evaluated:
You can add multiple conditions by clicking the "Add Condition" button again and again, or delete the condition by clicking on the trashcan to the right of the condition text box.
You should notice the elephant in the room at this point: what the ^$%* is a "logic app formula"???. Well, that'll be the subject of another blog post as it's a biiiiiig subject. There's a whole formula language that is used throughout logic apps, including expressions, functions, conditions, etc.
An example of a condition formula would be:
The above condition says: If the API App called "apiapp1" has a status of TRUE OR the value output of the API App called "apiapp2" has a value greater than 0, then continue.
And this applies to if-then-else statements as well: to do an if-then-else you need to have one condition for the if part (e.g. if output value = 10); and one opposing condition for the else part (e.g. if output value != 10). Once you've been doing it for a while it starts to make more sense. The difficult part is that the conditions are now part of the API app definition, which is the biggest change to get your head around.
Once I get on to talking about formulas, I'll give some more examples of conditional statements.
Looping is handled in a similar way to conditional statements: rather than there being a looping shape or app, you simply tell your API App that it should loop over the output from a previous API App or Trigger.
You do this from the same place as for setting conditions: click the gear icon at the top right of an API App in your logic app, and select "Repeat over a list":
You then get a text box, where you can type in the repeat formula - but luckily, you also get a button that allows you to select the output from a previous API App or Trigger as long as that API App or Trigger returns a list as defined by its API. This explains why sometimes you may not see any options when you click the button:
If you want to remove the repeat operation, click the gear icon and select "Do not repeat over a list".
Under the covers, setting a repeat formula generates something like this in the Logic App JSON:
repeat : "@action('apiapp1').outputs.messages"
And that's how you do looping in Logic Apps.
I appreciate I've given a quick runthrough on what is quite a complex subject - I'll be covering this more in forthcoming blog posts where I'll give some samples, and also give some more detail on the Logic App formula language.