The Switch() in Power Automate is a little interesting to me, in theory its a lookup, which any Excel user will tell you is probably the most fundamental function of Excel (v/xlookup of course). And as Power Automate is aimed at citizen developers who most likely used Excel before, its strange its not used very often.
I see nested If()'s all the time, but rarely a Switch, and I think its for a few reasons:
- Templates & Copilot prodomently use If()
- Most documentation/blogs/guides use If()
- Switch() can only do one logic (each branch can only check same thing)
- It doesnt scale well
- In the designer the horizontal expansion is not user friendly
I think its probably the last two that have the the biggest impact.
It doesn't scale well
Continually having to add branches is not the best way to scale. This often requires duplication of code, and worst of all a deployment.
In the designer the horizontal expansion is not user friendly
Working on a big Switch() is simply awful, scrolling sideways is goes against all the muscle memory of moving vertically. And because the rest of the flow is vertical you have to do a lot of scrolling to got back on path. The new UI is definitely an improvement, especially with the zoom, but that bad first impression will take a lot to get over.
Luckily there is a better way to do a Switch(), which scales infinitely and is a lot easier to build with.
The Super Switch() does 2 important things, keeps everything vertical, and best of all, outsources the branches from Power Automate (well kind of).
There are 3 levels to the Super Switch:
- Variables
- HTTP
- Delegated
Variables
The way the Super Switch works is following the Excel way, we move the branches to a table (either SharePoint or Dataverse). We use the filter query to get the record we like and then it returns our configs/variables.
We then pass those configs into our actions and we get our branching logic without branches.
As you may have guessed, because we are only have variables to use, it won't be able to do actions, well actually it can, and that's when it gets a little more complex.
2. HTTP
So if we are limited to just variables then lets use a action that is more flexible, and you guessed it that's the HTTP actions. We are now limited to Microsoft Graph endpoints but that covers a lot of scenarios (you could use the http action and do a lot more, but be careful how you store any credentials to auth).
Our look up table can pass the end points we want, so we are no longer scoped to same actions per branch, just same connections.
We use the replace() function to update the config response (good news is if the placeholder for the input isn't there it is simply ignored), so we are not limited to same inputs per branch.
Example
In the below example we are doing a get item and a create item, they use some inputs that are the same, but the get has dynamic url, and the create a dynamic body. As you can see the replace() is used on both of the dynamic inputs, the create doesn't have a '{id}' so the replace() function just returns the raw input, just as we want. And as the the get body is blank, it does the same.
site
json(outputs('Get_items_2')?['body/value'][0]?['json']?['site'])
type
json(outputs('Get_items_2')?['body/value'][0]?['json']?['type'])
url
replace(
json(outputs('Get_items_2')?['body/value'][0]?['json']?['url'])
,
'{id}'
,
triggerBody()['text_1']
)
body
replace(
replace(
json(outputs('Get_items_2')?['body/value'][0]?['json']?['body'])
,
'{title}'
,
triggerBody()['text_2']
)
,
'{description}'
,
triggerBody()['text_2']
)
We can also be creative, with branches for all connections or run afters, and use coalesce to get the action that responds.
3. Delegated
So you need full flexibility, with totally different actions in each logic branch, well there is a way and that's to delegate the actions to Child Flows 😎
Our List has all the conditions we want to check and sends back the childflow to call.
Though these child flows are a little different, as we can't dynamically call childflows.
As in if I had the below,
I should be able to peak the code,
and paste it in dynamically with the right schema:
But for some reason it throws error when try and save.
But luckily there is a workaround, a HTTP flow trigger (but don't worry no SPN needed for auth as we are being creative).
Securing the HTTP Child flow
We simply replace the Manual trigger for our childflow and add the 'When a HTTP request is received'.
We add a trigger condition that checks for a apiKey header, it's not the best way to do it (as the apiKey is stored in plain text inside the flow definition), but its secure enough for what we need.
Child Flow
We then add in the exact same json schema we used for the childflows and then save to get the trigger url.
In our config list we store the flows trigger url and the apiKey, along again with the same info from the HTTP version (type, url, body).
Parent Flow
The parent flow uses the HTTP action, just like we did with HTTP Super Switch, but now we can call any combination of connections.
We can add new branches by adding to the config list and creating a new 'Child' flow.
Although the normal Switch covers most use cases, having a selection of Super Switches is always useful, and this creative approach can be leveraged for other solutions too.
As always copy of a demo solution can be found in my GitHUb repo here
If you would like to get notified every new blog (I also do a few in the Power Platform Community), subscribe below
Top comments (6)
Coming from a coding background, I fear this is solving a problem that doesnt exist. Nested ifs are terrible design (a “code smell”), which is why switches are so good. You say it doesnt scale well, but then introduce data based off SP (a potential massive risk), JSON parsing, JSON parsing and HTTP - all of which need maintaining and cause extra actions towards the daily performance limits.
The branches are the actions and part of the condition and work exactly the same way as C# - switch defines the variable being checked against (it being a variable is good - you set the value earlier in the flow/method), this is the “x =“ part of an if. The case is the value “y”. So the whole thing is like doing x=y, x=z, etc. Each case could then call common functionality via a method, or child flow.
Personally, i think switches are concise and clear as they are and wouldnt think about this just to make it visually less wide.
Totally agree nested If's are not right, I personally prefer guard clauses.
You are right this adds completely, and is very much aimed at more experienced developers and niche cases.
The reason it doesn't scale well is a power automote UI issue, it's hard to navigate/use and the high use of actions through duplication causes browser to freeze.
I'm interested in the risks of using SP, as in my experience 90% of all power platform data is stored there.
Yeah fair enough, its a hard one as id hate the idea of supporting this for UI issues, but you need the UI…
With SP, its more that security model isnt anywhere near as robust as dataverse. Its a document management system, not a database and i feel much if the PP industry is using it as the latter because its free. To me, that and a million different canvas apps is not the way to go and will become an unsupportable mess when people leave PP for the next “cool” tech.
We use it and its excellent, but only for documents, alongsiden DV, custom systems and off the peg systems. “Pick the right tool for the job” as we say. Theres a reason D365 exists.
Yep agree with SP, it's lacking security features and is heavily over used in pp, too much security by obscurity. And yep it isn't a database, but for config lists its ok, especially when it's used by flows and no user management needed.
I do agree with your overall sentiment, KISS is the way to go and the normal switch works in most cases.
Yeah config is fine, I guess it depends on the end usage. For us, most things are gonna be in D365 (and need to utilise more and more of the out of the box functionality), so as we're already paying for Dataverse, we put lookup data there and have very little need for canvas apps. As you said, it's treating each need as its own and managing that appropriately.
Cool tip to have in the tool belt !!