Dynamics CRM Webhook vs Power Automate Cloud Flow vs Plugin
Do you know Dynamics CRM Webhooks? The definition from the official documentation: CRM Webhooks is a feature that enables CRM to call other URLs using HTTP patterns with publish/subscribe patterns. , I do not quite agree with the definition because we still can register the plugin in Sync mode instead of Async. Meaning, that if the URL endpoint we call gets an error and we set the plugin step as Sync, it will stop the whole process which violates the Pub/Sub pattern.
CRM Webhook
The detailed implementation that I read is fromPriyesh Wagh which you can check here. But long story short, I was intrigued by how can we implement the "low code" to do this in the webhooks and why we need to use this method compared to the other methods (Plugin, PowerAutomate Cloud Flow). My original idea was to create Cloud Flow that is triggered using Webhooks. The flow will be:
Webhook creation flow
Here is the Flow that I prepare (for testing purposes):
Simple HTTP flow
Update per 19 June 2021
I've got an explanation from zakabena that I am supposed to register the HttpQueryString without encoding especially the sp parameter from %2Ftriggers%2Fmanual%2Frun into /triggers/manual/run. And he is correct!
Then here is how I register the Webhook Endpoint (Register > Register New Webhook) in the plugin registration tool:
Webhook registration
Here is the plugin step that I set up for this demonstration:
Plugin step for webhook
From this point, our webhook is done. You can go to any account change it and click Save. Then you will see that your Flow is successfully triggered.
Here are the Request Headers that CRM sends when we call Webhook (result from webhook.site):
Headers that provided by Webhook request
Below is the detailed information on the HTTP Body request that CRM will send if we target it in the various messages.
Request body JSON value if we set the plugin step as Create:
{
"BusinessUnitId": "d8aa8675-25b1-eb11-8236-000d3ac912e3",
"CorrelationId": "d2053f9b-6108-45d5-99d1-05163024a8fe",
"Depth": 1,
"InitiatingUserAzureActiveDirectoryObjectId": "00000000-0000-0000-0000-000000000000",
"InitiatingUserId": "cbb18675-25b1-eb11-8236-000d3ac912e3",
"InputParameters": [
{
"key": "Target",
"value": {
"__type": "Entity:http://schemas.microsoft.com/xrm/2011/Contracts",
"Attributes": [
{
"key": "territorycode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "owningbusinessunit",
"value": {
"__type": "EntityReference:http://schemas.microsoft.com/xrm/2011/Contracts",
"Id": "d8aa8675-25b1-eb11-8236-000d3ac912e3",
"KeyAttributes": [],
"LogicalName": "businessunit",
"Name": null,
"RowVersion": null
}
},
{
"key": "address2_shippingmethodcode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "isprivate",
"value": false
},
{
"key": "followemail",
"value": true
},
{
"key": "donotbulkemail",
"value": false
},
{
"key": "donotsendmm",
"value": false
},
{
"key": "createdon",
"value": "/Date(1623328083000)/"
},
{
"key": "statecode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 0
}
},
{
"key": "businesstypecode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "donotpostalmail",
"value": false
},
{
"key": "ownerid",
"value": {
"__type": "EntityReference:http://schemas.microsoft.com/xrm/2011/Contracts",
"Id": "cbb18675-25b1-eb11-8236-000d3ac912e3",
"KeyAttributes": [],
"LogicalName": "systemuser",
"Name": null,
"RowVersion": null
}
},
{
"key": "donotbulkpostalmail",
"value": false
},
{
"key": "name",
"value": "Temmy"
},
{
"key": "donotemail",
"value": false
},
{
"key": "address2_addresstypecode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "donotphone",
"value": false
},
{
"key": "transactioncurrencyid",
"value": {
"__type": "EntityReference:http://schemas.microsoft.com/xrm/2011/Contracts",
"Id": "d7d10452-35b1-eb11-8236-000d3ac912e3",
"KeyAttributes": [],
"LogicalName": "transactioncurrency",
"Name": null,
"RowVersion": null
}
},
{
"key": "modifiedby",
"value": {
"__type": "EntityReference:http://schemas.microsoft.com/xrm/2011/Contracts",
"Id": "cbb18675-25b1-eb11-8236-000d3ac912e3",
"KeyAttributes": [],
"LogicalName": "systemuser",
"Name": null,
"RowVersion": null
}
},
{
"key": "emailaddress1",
"value": "temmy.raharjo@outlook.com"
},
{
"key": "statuscode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "modifiedonbehalfby",
"value": null
},
{
"key": "preferredcontactmethodcode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "accountid",
"value": "5677734c-e7c9-eb11-bacc-000d3aa2b8f0"
},
{
"key": "createdby",
"value": {
"__type": "EntityReference:http://schemas.microsoft.com/xrm/2011/Contracts",
"Id": "cbb18675-25b1-eb11-8236-000d3ac912e3",
"KeyAttributes": [],
"LogicalName": "systemuser",
"Name": null,
"RowVersion": null
}
},
{
"key": "donotfax",
"value": false
},
{
"key": "merged",
"value": false
},
{
"key": "customersizecode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "marketingonly",
"value": false
},
{
"key": "accountratingcode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "shippingmethodcode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "creditonhold",
"value": false
},
{
"key": "modifiedon",
"value": "/Date(1623328083000)/"
},
{
"key": "participatesinworkflow",
"value": false
},
{
"key": "accountclassificationcode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "address2_freighttermscode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "exchangerate",
"value": 1
}
],
"EntityState": null,
"FormattedValues": [
{
"key": "territorycode",
"value": "Default Value"
},
{
"key": "address2_shippingmethodcode",
"value": "Default Value"
},
{
"key": "isprivate",
"value": "No"
},
{
"key": "followemail",
"value": "Allow"
},
{
"key": "donotbulkemail",
"value": "Allow"
},
{
"key": "donotsendmm",
"value": "Send"
},
{
"key": "createdon",
"value": "2021-06-10T20:28:03+08:00"
},
{
"key": "statecode",
"value": "Active"
},
{
"key": "businesstypecode",
"value": "Default Value"
},
{
"key": "donotpostalmail",
"value": "Allow"
},
{
"key": "donotbulkpostalmail",
"value": "No"
},
{
"key": "donotemail",
"value": "Allow"
},
{
"key": "address2_addresstypecode",
"value": "Default Value"
},
{
"key": "donotphone",
"value": "Allow"
},
{
"key": "statuscode",
"value": "Active"
},
{
"key": "preferredcontactmethodcode",
"value": "Any"
},
{
"key": "donotfax",
"value": "Allow"
},
{
"key": "merged",
"value": "No"
},
{
"key": "customersizecode",
"value": "Default Value"
},
{
"key": "marketingonly",
"value": "No"
},
{
"key": "accountratingcode",
"value": "Default Value"
},
{
"key": "shippingmethodcode",
"value": "Default Value"
},
{
"key": "creditonhold",
"value": "No"
},
{
"key": "modifiedon",
"value": "2021-06-10T20:28:03+08:00"
},
{
"key": "participatesinworkflow",
"value": "No"
},
{
"key": "accountclassificationcode",
"value": "Default Value"
},
{
"key": "address2_freighttermscode",
"value": "Default Value"
}
],
"Id": "5677734c-e7c9-eb11-bacc-000d3aa2b8f0",
"KeyAttributes": [],
"LogicalName": "account",
"RelatedEntities": [],
"RowVersion": null
}
}
],
"IsExecutingOffline": false,
"IsInTransaction": true,
"IsOfflinePlayback": false,
"IsolationMode": 1,
"MessageName": "Create",
"Mode": 0,
"OperationCreatedOn": "/Date(1623328085203)/",
"OperationId": "0dfe0cff-0bc3-4997-953b-e62ba9a800f6",
"OrganizationId": "e7a95a8c-862b-41d9-adcf-b1c035098804",
"OrganizationName": "unqe7a95a8c862b41d9adcfb1c035098",
"OutputParameters": [
{
"key": "id",
"value": "5677734c-e7c9-eb11-bacc-000d3aa2b8f0"
}
],
"OwningExtension": {
"Id": "ccdc065b-95c9-eb11-bacc-000d3aa2b8f0",
"KeyAttributes": [],
"LogicalName": "sdkmessageprocessingstep",
"Name": "test: Update of account",
"RowVersion": null
},
"ParentContext": {
"BusinessUnitId": "d8aa8675-25b1-eb11-8236-000d3ac912e3",
"CorrelationId": "d2053f9b-6108-45d5-99d1-05163024a8fe",
"Depth": 1,
"InitiatingUserAzureActiveDirectoryObjectId": "00000000-0000-0000-0000-000000000000",
"InitiatingUserId": "cbb18675-25b1-eb11-8236-000d3ac912e3",
"InputParameters": [
{
"key": "Target",
"value": {
"__type": "Entity:http://schemas.microsoft.com/xrm/2011/Contracts",
"Attributes": [
{
"key": "emailaddress1",
"value": "temmy.raharjo@outlook.com"
},
{
"key": "name",
"value": "Temmy"
},
{
"key": "donotpostalmail",
"value": false
},
{
"key": "donotphone",
"value": false
},
{
"key": "donotfax",
"value": false
},
{
"key": "donotemail",
"value": false
},
{
"key": "donotbulkemail",
"value": false
},
{
"key": "followemail",
"value": true
},
{
"key": "preferredcontactmethodcode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "creditonhold",
"value": false
},
{
"key": "statuscode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "accountratingcode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "transactioncurrencyid",
"value": {
"__type": "EntityReference:http://schemas.microsoft.com/xrm/2011/Contracts",
"Id": "d7d10452-35b1-eb11-8236-000d3ac912e3",
"KeyAttributes": [],
"LogicalName": "transactioncurrency",
"Name": null,
"RowVersion": null
}
},
{
"key": "ownerid",
"value": {
"__type": "EntityReference:http://schemas.microsoft.com/xrm/2011/Contracts",
"Id": "cbb18675-25b1-eb11-8236-000d3ac912e3",
"KeyAttributes": [],
"LogicalName": "systemuser",
"Name": null,
"RowVersion": null
}
},
{
"key": "businesstypecode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "shippingmethodcode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "address2_shippingmethodcode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "territorycode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "marketingonly",
"value": false
},
{
"key": "accountclassificationcode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "donotbulkpostalmail",
"value": false
},
{
"key": "address2_freighttermscode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "donotsendmm",
"value": false
},
{
"key": "isprivate",
"value": false
},
{
"key": "address2_addresstypecode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "participatesinworkflow",
"value": false
},
{
"key": "merged",
"value": false
},
{
"key": "customersizecode",
"value": {
"__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
"Value": 1
}
},
{
"key": "accountid",
"value": "5677734c-e7c9-eb11-bacc-000d3aa2b8f0"
}
],
"EntityState": null,
"FormattedValues": [],
"Id": "5677734c-e7c9-eb11-bacc-000d3aa2b8f0",
"KeyAttributes": [],
"LogicalName": "account",
"RelatedEntities": [],
"RowVersion": null
}
},
{
"key": "x-ms-app-name",
"value": "new_insurgoapp"
},
{
"key": "SuppressDuplicateDetection",
"value": false
}
],
"IsExecutingOffline": false,
"IsInTransaction": true,
"IsOfflinePlayback": false,
"IsolationMode": 1,
"MessageName": "Create",
"Mode": 0,
"OperationCreatedOn": "/Date(1623328083547)/",
"OperationId": "0dfe0cff-0bc3-4997-953b-e62ba9a800f6",
"OrganizationId": "e7a95a8c-862b-41d9-adcf-b1c035098804",
"OrganizationName": "unqe7a95a8c862b41d9adcfb1c035098",
"OutputParameters": [],
"OwningExtension": {
"Id": "ffc9bb1b-ea3e-db11-86a7-000a3a5473e8",
"KeyAttributes": [],
"LogicalName": "sdkmessageprocessingstep",
"Name": "ObjectModel Implementation",
"RowVersion": null
},
"ParentContext": null,
"PostEntityImages": [],
"PreEntityImages": [],
"PrimaryEntityId": "5677734c-e7c9-eb11-bacc-000d3aa2b8f0",
"PrimaryEntityName": "account",
"RequestId": "0dfe0cff-0bc3-4997-953b-e62ba9a800f6",
"SecondaryEntityName": "none",
"SharedVariables": [
{
"key": "IsAutoTransact",
"value": true
},
{
"key": "x-ms-app-name",
"value": "new_insurgoapp"
},
{
"key": "DefaultsAddedFlag",
"value": true
},
{
"key": "ChangedEntityTypes",
"value": [
{
"__type": "KeyValuePairOfstringstring:#System.Collections.Generic",
"key": "account",
"value": "Update"
}
]
}
],
"Stage": 30,
"UserAzureActiveDirectoryObjectId": "00000000-0000-0000-0000-000000000000",
"UserId": "cbb18675-25b1-eb11-8236-000d3ac912e3"
},
"PostEntityImages": [],
"PreEntityImages": [],
"PrimaryEntityId": "5677734c-e7c9-eb11-bacc-000d3aa2b8f0",
"PrimaryEntityName": "account",
"RequestId": "0dfe0cff-0bc3-4997-953b-e62ba9a800f6",
"SecondaryEntityName": "none",
"SharedVariables": [
{
"key": "IsAutoTransact",
"value": true
},
{
"key": "x-ms-app-name",
"value": "new_insurgoapp"
},
{
"key": "DefaultsAddedFlag",
"value": true
}
],
"Stage": 40,
"UserAzureActiveDirectoryObjectId": "00000000-0000-0000-0000-000000000000",
"UserId": "cbb18675-25b1-eb11-8236-000d3ac912e3"
}
Request body JSON value if we set the plugin step as Delete:
{
"BusinessUnitId": "d8aa8675-25b1-eb11-8236-000d3ac912e3",
"CorrelationId": "db3d5da1-a6ed-4981-b761-f0fad152f5c0",
"Depth": 1,
"InitiatingUserAzureActiveDirectoryObjectId": "00000000-0000-0000-0000-000000000000",
"InitiatingUserId": "cbb18675-25b1-eb11-8236-000d3ac912e3",
"InputParameters": [
{
"key": "Target",
"value": {
"__type": "EntityReference:http://schemas.microsoft.com/xrm/2011/Contracts",
"Id": "be69f3f3-74c8-eb11-bacc-000d3aa2b8f0",
"KeyAttributes": [],
"LogicalName": "account",
"Name": null,
"RowVersion": null
}
}
],
"IsExecutingOffline": false,
"IsInTransaction": true,
"IsOfflinePlayback": false,
"IsolationMode": 1,
"MessageName": "Delete",
"Mode": 0,
"OperationCreatedOn": "/Date(1623326203276)/",
"OperationId": "317ce56d-3ba1-4fba-91f3-7cda27e890df",
"OrganizationId": "e7a95a8c-862b-41d9-adcf-b1c035098804",
"OrganizationName": "unqe7a95a8c862b41d9adcfb1c035098",
"OutputParameters": [],
"OwningExtension": {
"Id": "ccdc065b-95c9-eb11-bacc-000d3aa2b8f0",
"KeyAttributes": [],
"LogicalName": "sdkmessageprocessingstep",
"Name": "test: Update of account",
"RowVersion": null
},
"ParentContext": {
"BusinessUnitId": "d8aa8675-25b1-eb11-8236-000d3ac912e3",
"CorrelationId": "db3d5da1-a6ed-4981-b761-f0fad152f5c0",
"Depth": 1,
"InitiatingUserAzureActiveDirectoryObjectId": "00000000-0000-0000-0000-000000000000",
"InitiatingUserId": "cbb18675-25b1-eb11-8236-000d3ac912e3",
"InputParameters": [
{
"key": "Target",
"value": {
"__type": "EntityReference:http://schemas.microsoft.com/xrm/2011/Contracts",
"Id": "be69f3f3-74c8-eb11-bacc-000d3aa2b8f0",
"KeyAttributes": [],
"LogicalName": "account",
"Name": null,
"RowVersion": null
}
},
{
"key": "x-ms-app-name",
"value": "new_insurgoapp"
}
],
"IsExecutingOffline": false,
"IsInTransaction": true,
"IsOfflinePlayback": false,
"IsolationMode": 1,
"MessageName": "Delete",
"Mode": 0,
"OperationCreatedOn": "/Date(1623326199666)/",
"OperationId": "317ce56d-3ba1-4fba-91f3-7cda27e890df",
"OrganizationId": "e7a95a8c-862b-41d9-adcf-b1c035098804",
"OrganizationName": "unqe7a95a8c862b41d9adcfb1c035098",
"OutputParameters": [],
"OwningExtension": {
"Id": "6acabb1b-ea3e-db11-86a7-000a3a5473e8",
"KeyAttributes": [],
"LogicalName": "sdkmessageprocessingstep",
"Name": "ObjectModel Implementation",
"RowVersion": null
},
"ParentContext": null,
"PostEntityImages": [],
"PreEntityImages": [],
"PrimaryEntityId": "be69f3f3-74c8-eb11-bacc-000d3aa2b8f0",
"PrimaryEntityName": "account",
"RequestId": "317ce56d-3ba1-4fba-91f3-7cda27e890df",
"SecondaryEntityName": "none",
"SharedVariables": [
{
"key": "IsAutoTransact",
"value": true
},
{
"key": "x-ms-app-name",
"value": "new_insurgoapp"
},
{
"key": "ChangedEntityTypes",
"value": [
{
"__type": "KeyValuePairOfstringstring:#System.Collections.Generic",
"key": "account",
"value": "Update"
}
]
}
],
"Stage": 30,
"UserAzureActiveDirectoryObjectId": "00000000-0000-0000-0000-000000000000",
"UserId": "27a496d8-2bc1-4089-900f-0cb6cd5bdb4a"
},
"PostEntityImages": [],
"PreEntityImages": [],
"PrimaryEntityId": "be69f3f3-74c8-eb11-bacc-000d3aa2b8f0",
"PrimaryEntityName": "account",
"RequestId": "317ce56d-3ba1-4fba-91f3-7cda27e890df",
"SecondaryEntityName": "none",
"SharedVariables": [
{
"key": "IsAutoTransact",
"value": true
},
{
"key": "x-ms-app-name",
"value": "new_insurgoapp"
}
],
"Stage": 40,
"UserAzureActiveDirectoryObjectId": "00000000-0000-0000-0000-000000000000",
"UserId": "27a496d8-2bc1-4089-900f-0cb6cd5bdb4a"
}
The summary of the information above is the Body Request that Webhook will send is the JSON Value of the IPluginExecutionContext.
Instant Cloud Flow
We also can call other API/other action using Power Automate Cloud Flow. We can use Microsoft Dataverse connector and here is the sample of the flow:
Using Microsoft Dataverse connector to replace webhook
This method is easier with the "low code" methodology. You can set up your flow by just selecting the triggers and actions you want to apply.
Plugins
The last method is using a custom plugin. We can create our implementation to call the API without limitation through the code. We can set any headers and body to what we need. Here is the sample code that I wrote:
using Microsoft.Xrm.Sdk;
using RestSharp;
using System;
namespace Demo.Plugins
{
public class PostUpdateOperation : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
var pluginExecutionContext = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
var client = new RestClient("YOUR-API-URL");
var request = new RestRequest(Method.POST);
request.AddJsonBody(pluginExecutionContext);
client.Execute(request);
}
}
}
I'm using RestSharpwhich means that you need to merge the assemblies.
Summary
In the world of Power Platform, we got a lot of features that is overlap with each other. All the functionality that CRM Webhook can be done in plugin and flow and vice versa. So here is the pros and cons in my opinion:
| Description | Webhook | Flow | Plugin |
|---|---|---|---|
| Pros | Setup is fast, just need to register endpoint URL + plugin step | Easy to setup (low code) | You can customize as much as you can |
| Cons | Input is limited (PluginExecutionContext value only, headers depends on the implementation) | Limitation depends on the connector provider, Pricing, Async only | Needs coding |
Comparison
What do you think?
Leave a comment
Your comment is sent privately to the author and isn't published on the site.