Extend Your Flows with C# Code in Common Data Service
Power Automate is an awesome tool to build processes whether it is as simple as just sending out an e-mail or more advanced like a multi-level approval process. Another plus is that they can span across a vast amount of different services.
But what if the built-in connectors and actions do not fit your needs? Or what if your process is so complex that in the end your flow would look like a huge mess? In today’s blog post we will talk about how to extend your flows with C# based custom code running in Common Data Service so you can move some of your logic to a different layer.
Custom Activities to the rescue
Power Platform itself offers two ways to use C# code on the backend side. One of them are plug-ins that can trigger automatically on certain events – like when creating a new record. The second one is custom code activities which can be called from inside processes (like workflows and actions).
And guess what? Actions work as endpoints that you can call even from Power Automate flows and they support input and output parameters. Sounds like an awesome way to get your flows to the next level with some custom code-based logic.
Keep in mind that this does not necessarily means that you will need to store any of your data inside Common Data Service. Only your backend code will reside inside of it.
If you are not familiar with writing extension code for Common Data Service, please read the Workflow extensions guide on Microsoft Docs that will help you get started!
Why not go with APIs?
The more experienced developers might already have come to the conclusion that what we want to do here can be easily achieved by using Web APIs! This is true and you could even further extend your solution by creating a custom connector for your API!
However, in those occasions when you are working with dev-test-production environments and solutions in Common Data Service, you will need a way to run that backend logic in the specific environment. By going this direction, you will be able to deploy your code within solutions.
Overview of the Solution
The solution will consist of the following components:
- Custom Activity (C# code): This code will contain all our backend logic. This can be as simple as adding two numbers, or can be as complex as connecting to 3rd party services, calling the Organization Service, etc.
- Flow (Power Automate): We will be creating a new flow (or you can extend your own existing ones) to call the Action we will just create.
In the end it will run as follows:
- The Flow will be triggered and it will call the Action we have created inside of Common Data Service with our defined input parameters.
- The Action contains a series of steps which will run in order. Our first step is to call our Custom Activity C# code with the input parameters forwarded to it. The Custom Activity will return the result to our Action.
- The Action will forward the result output parameter of the Custom Activity to the Flow as its own output parameter.
- The Flow will receive the result and will be able to continue working with it.
It might sound a little bit complicated by first, but let’s walk through the steps one by one to see how this solution builds up.
The managed solution including the custom activity assembly and the action process can be downloaded from my GitHub releases page: https://github.com/Bhawk90/CommonDataService-CustomActivity/releases
Create Your Basic Custom Activity
I have prepared a simple code for our very first code based Custom Activity. It will not do anything more than just adding two numbers provided as input parameters and will provide you the result in an output parameter.
Head over to the following URL to find the sample code and clone the repository: https://github.com/Bhawk90/CommonDataService-CustomActivity/blob/master/AdditionActivity.cs
You can go ahead and compile the code by yourself – nothing more then a Visual Studio and .NET Framework 4.6.2 is required -, or you can go ahead and download the latest release package with the compiled binaries included.
Once you have the compiled binaries, you should install them by using the Plugin Registration Tool which you can install by following this guide. Once you have it installed:
- Log in to your Common Data Service environment
- Choose Register New Assembly
- Browse to the folder of your pre-compiled binaries
- Choose CDS.CustomActivities.dll
- Select all Workflow Activities and click Register Selected Plugins
If you are familiar with custom plug-ins and code activities inside Common Data Service, this is exactly what you’ve been doing. You have access to all the things like Tracing Service, Execution Context and Organization Service!
Create the Action
Now that we have our custom activity in place, we need an Action to invoke it. In order to do it, navigate to https://make.powerapps.com/ and create a new process. Sadly, at the time of writing this was not supported on the new interface, so switch back by choosing Advanced Settings in the top right menu.
From here, you should navigate to the Customizations section and there choose Customize the System. Click New in the component list menu and select Process to create a new process. Fill the form as shown below.
Next, we will set up our Action to have two inputs, one output. These inputs and outputs will be forwarded to our Custom Activity to add the two numbers and give us the output we expect.
- Add a new input with the name of OperandA, type of Integer. Set it to be required!
- Add another input with the name of OperandB, type of Integer. This should be set to required too!
- Add an output with the name of Result, type of Integer.
- Add a new Step to the Process, select CDS.CustomActivities.AdditionActivity from the presented list.
- Click on Set Properties and set Operand A and Operand B properties to have the value of our previously created input arguments. Hit Save & Close.
- Add another Step to the Process, select Assign Value. Choose Set Properties.
- Type in Result for the Statement Label, select Result for the Name and the Value should be the Result output property of our AdditionActivity. Be careful not to choose Result from the arguments!
- Hit Save & Close and then hit Save to save changes in your Process.
- You should be presented with the following.
If everything seems to be right, go ahead and Activate your process. You can close this window now.
Build the Flow
For this example, we will keep our Power Automate flow as simple as possible. This doesn’t mean that you cannot use this in advanced flows with a hundred actions, multiple connectors, etc.
We will create a flow that can be manually triggered with two number parameters and we expect it to write the result into a variable. Now the magic happens in the second action called Perform an unbound action.
The Common Data Service (Current Environment) connector has two options running actions from the current environment:
- Perform a bound action: When you create an Action that has an entity specified that you will run it for, you need to use this. Bound actions always run for a specific record of an entity type.
- Perform an unbound action: When you do not define any entity for your Action – so it is a global action – you will be calling a so-called unbound action that is not bound to a specific entity type.
The Action Name parameter will present you a list of all Actions available inside your environment. Beware, it will take a while until it loads up 😉 The name of your Action is the Unique Name of the process so it will always start with a prefix.
OperandA and OperandB are the input parameters of the Action itself which you should provide. And as you would expect, the Action will return the Result output parameter which is filled by our Process.
After we have performed our Action, we can use its dynamic outputs to work with them – in this case we will see the Result as an output.
Power Automate flows provide a really easy way (especially) for citizen developers to build up complex business processes that are not tied to a simple service. But with simplicity comes limitations.
Flows might not be the best solution in scenarios where very complex processes are required to solve our customers’ needs. The flow will become a huge mess with lots of actions, conditions which nobody will fully understand in the end. In these cases, a combination of flows and custom code might come handy.
If you have any questions or have some tips/suggestions for your fellow developers, go ahead and sound your comments below! 😉