Executing Dynamics 365 workflows from Microsoft Flow

The only Dynamics 365 actions that Microsoft Flow offers right now are "create a new record" and "list records," but with just a bit of additional effort it's possible to access all the capabilities of the Web API. Today I will show how to create a Microsoft Flow that queries a set of accounts and executes a workflow for each one.

My Flow comprises five separate actions, which you can see in the screenshot below:
Flow overview

  1. The request trigger - In this case I am triggering my Flow by making an empty HTTP POST request, but you could use any supported trigger.
  2. A "getauthtoken" HTTP request - Flow knows how to query a list of CRM records without requiring any additional authentication, but in order to work with the Web API directly, it's necessary to get an OAuth2 token from Active Directory like I described in my recent "Dynamics 365 and Node.js integration using the Web API" post.
  3. A Dynamics 365 list records action - This action queries Dynamics 365 for the accounts on which the workflow will be executed.
  4. An "apply to each" loop - This loops through the returned accounts from the previous step and executes the workflow for each one.
  5. A response step - This action sends back a success message regardless of what happens in the previous steps. Ideally I would handle errors appropriately here.

Let's take a closer look at each action.

Triggering the Flow

As I mentioned above, my Flow is triggered from an empty POST request, but you could use a different trigger.
Request trigger

Getting the OAuth token

In order to get an OAuth token, my Flow uses an HTTP request action to post the following parameters to the AD token endpoint:

  1. client_id - registered client id from AD
  2. resource - root path to your Dynamics 365 org (https://XXXXX.crm.dynamics.com, for example)
  3. username - Dynamics 365 username
  4. password - Dynamics 365 user password
  5. grant_type = "password"

The AD token endpoint expects data to be sent as application/x-www-form-urlencoded content, so you have to set the request header and manually build the POST string. The POST string should look like this:

client_id=REGISTERED_CLIENT_ID&resource=https://CRMORG.crm.dynamics.com&username=USERNAME&password=PASSWORD&grant_type=password  

Interestingly enough, you do not have to URI encode your parameters to escape special characters in general, though I suspect it would be necessary if your password contains "&" or "="
characters.

Here's what my configured action looks like:

Request OAuth token

(It would make more sense store all these string configuration settings as variables using Flow "compose" actions, but I chose not to do that for this post to make the overall sequence easier to follow.)

Retrieving records

The next step in my Flow queries Dynamics 365 for accounts using the native "list records" functionality. This action does not require the OAuth token retrieved in the previous step.

Retrieve account records

Looping through retrieved records

Next my Flow use an "apply to each" step to loop through the retrieved accounts and then execute the workflow.
Loop through retrieved accounts

Calling the workflow requires POSTing a JSON object containing the accountid value to the Dynamics 365 Web API endpoint (note the workflow id is included in the endpoint here), and the Web API expects the OAuth token from earlier to be included in the request headers. Flow does not automatically know how to parse the JSON response from the OAuth token retrieval request, so it won't show up in the dynamic content menu, but you can access it using this format @{body('HTTP REQUEST ACTION NAME').access_token}.

Here's my request headers object:

{
"Authorization": "Bearer @{body('getauthtoken').access_token}",
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
"Accept": "application/json",
"Content-Type": "application/json; charset=utf-8"
}

Once you save the Flow, the UI will replace the @{body('HTTP REQUEST ACTION NAME').access_token} with something that looks like a dynamic content placeholder as you can see in the screenshot below.
Call workflow

Sending a response

Finally my Flow uses a response action to send a message back to the client. As I mentioned above, I should do some error handling here, but for now I am just sending back "success" no matter what happens earlier in the Flow.
Respond to caller

When I call this Flow via Postman, I get this output:
Call Flow from Postman

Checking the Flow run log shows me this visual with all green checks.
Flow run success

And I can expand the individual actions to see what happened in each step. Here you can see the loop of execute workflow calls.
Flow run success detail

Wrapping up

Now that I've shown how you could call a Dynamics 365 workflow from Microsoft Flow, it's worth asking whether you actually should call a Dynamics 365 workflow from Microsoft Flow.
Could/should

Given the state of Microsoft Flow's native Dynamics 365 support today, I would say no. At this point Flow's visual designer makes it a lot harder to build this functionality than it is if you use Azure Functions as I discussed in these earlier posts:

  1. Scheduling Dynamics 365 workflows with Azure Functions and Node.js
  2. Scheduling Dynamics 365 workflows with Azure Functions and Python
  3. Scheduling Dynamics 365 workflows with Azure Functions and C#

For more considerations on when to use Flow or something else, here is an interesting post from Microsoft that compares and contrasts its various "serverless" computing offerings: https://docs.microsoft.com/en-us/azure/azure-functions/functions-compare-logic-apps-ms-flow-webjobs.

Although I think Flow isn't a great tool for this particular use case, I can envision some good uses in the Dynamics 365 space, and I will certainly be paying attention to see how it improves in the future. Thanks for reading!

comments powered by Disqus