I will start this post with exactly the same picture as the previous one to keep us all alert. Remember, Logic Apps have Inline Scripts now – there is no time to relax till we find an appropriate answer to this challenge:
And, even though I feel much better now keeping in mind that Azure Functions have proved to work quite well with the Flow yesterday (and, subsequently, with the Canvas Apps), there is one minor issue I did not mention since I did not want to undermine what was done.
See, Azure Functions are not solution-aware. They are not PowerPatform aware for that matter, so you might find it complicated to distribute Azure Functions with the solutions, especially if you are an ISV.
Any options? Is it, actually, a big issue?
Hm… to start with, Logic Apps are not solution-aware either. So, technically, PowerAutomate is already winning from the get go, since PowerAutomate Flows and Canvas Apps are solution aware. But, still, it would be nice to have an option of putting everything into a solution, sending it to the client, and living happily ever after.
This is why this post is going be about the Custom Actions!
“Heh…” – would say a seasoned Dynamics warrior… – “ I knew you would mention it”.
And rightly so (and, btw, if you are one, please feel free to take a seat back there for a while till we get to the Flows down below… Then come forward to read through the rest of this post). But, for those coming more from the Canvas App / Power Automate world, let’s start from the beginning.
So, what is an action?
“Actions and functions represent re-usable operations you can perform using the Web API”
https://docs.microsoft.com/en-us/powerapps/developer/common-data-service/webapi/use-web-api-actions
This is all in the context of CDS. There is Web API, there are actions, and we can reuse those actions through Web API (yes, through the SDK, too).
What is a CUSTOM action?
There are re-usable operations available out of the box, but we can create our own actions in CDS. Not surprisingly, those care called custom actions.
What does it have to do with adding custom code to PowerAutomate?
First, we can write code with custom actions. More details below.
And, second, there is a relatively new Common Data Service (Current Environment) connector which we can use to easily call custom actions from Flows:
Put those two together and you have custom code in PowerAutomate. Let’s do just that.
Logic apps should really start feeling the heat now. This connector is only available in Flows and PowerApps!
https://docs.microsoft.com/en-us/connectors/commondataserviceforapps/
Not that I have anything against Logic Apps, but we ought to have something unique on the PowerPlatform side, right?
Anyway, it’s time to create a custom action for the same regex example I used in the previous post.
1. Let’s switch to the classic solution designer (custom actions don’t seem to be available in the new designer yet)
2. Let’s create a new action (as a process)
For this one, there is no need to bound it to an entity
3. This action will have two input and one output parameter
4. No need for any workflow steps – we’ll have C# code instead
So, can simply activate the action
5. Now on to the C# code
Basically, we need a plugin. That plugin will kick in whenever an action is called (well, once there is a plugin, we’ll need to register it so it all gets connected)
Plugin development can be a rather long story which I tried to cover in my now-2-years-old-now course:
http://itaintboring.com/downloads/training/Plugin%20Development.pdf
Again, you will find complete code on github, but here is the essence of that plugin:
It’s almost a reincarnation of the Azure Function discussed in the previous post with some added plumbing to turn this code into a plugin.
6. We need to register the plugin
The process of registration involves using what is called a plugin registration tool:
You may need to download it first:
7. We need to link that plugin to the custom action created before
This involves creating a step in the plugin registration tool. Notice the message name – it’s, actually, the name of the custom action:
This took a while – about half an hour, but we have it all ready and can go back to the Flow now.
(Apparently, I cheated here since I had all those tools installed already and I knew what I was doing May take somewhat longer if you are doing it the first time, but you know where to find me if you have questions)
8. Creating the Flow (I am hoping seasoned Dynamics developers are back, btw)
The Flow is very similar to what it used to be for the Azure Function example. The only difference is that instead of calling an Azure Function through the HTTP connector, we will need to call an unbound action through a Common Data Service (Current Environment) connector:
9. Calling that Flow from the Canvas App
10. And here is the end result (which is no different from what we had before with Azure Functions)
So, then, compared to the Azure Functions, what is the difference?
- Custom Actions are CDS-based
- Azure Functions do not need a CDS
- Custom action calls will be counted against CDS request limits
- Azure Function calls will be priced according to Azure Functions pricing
- Custom actions can be added to the solutions (you will have to add the plugin, the action, and the step)
- Azure Functions will have to be deployed somehow, but they don’t need CDS
- Finally, since custom actions will be using plugins for the “code” part, it will be easy to connect to CDS from that plugin
- Azure Functions, if the need to connect to CDS, will have to create required connections, authenticate, etc
In other words… if you have a CDS instance there, and if you need to simplify devops, custom actions might work better. Except that there is that API request limits part which might make you think twice.
This is not over yet, though. It may take a few days before another post on this topic, but I’m hoping to take a closer look at the custom connectors soon.
Brilliant! I had considered this the other day when I heard that calling actions had been added, but it’s great to see it working for real! Another option would be to have a custom workflow activity, and use that as a step inside the Action.
Having some weird issue with mine, it doesn’t bring up any of the fields like data and pattern that i entered as inputs into my action in the flow, it seems to just bring up all the fields from the entity i am trying to use it with, despite using a global and unbound action… any suggestions?
after a closer look i figured out that i just wasn’t expecting the fields it brought up when i tried to pass an entity reference, just passing the reference as a string now.
Excellent article! Thank you!