Many to many relationships are everywhere, from good old marketing lists to web roles in Power Apps portals. The secret sauce is in the little hidden intersect entity holding the relationship together, those of you who used FetchXml Builder from XrmToolBox to craft a query, are very familiar with. The messages to control the relationship are appropriately named Tweedledum and Tweedledee Associate and Disassociate.
Wouldn’t that be nice to be able to automate some business processes when records are associated and disassociated? For example, when someone is added to a marketing list we might want to say hello or, when someone is no longer a portal administrator, we’d like to say “Nyah nyah nyah nyah nyah nyah”?
These little messages have been tormenting us for as long as I can remember. Power Automate has given me a glimpse of hope by accepting [manually entered] intersect entity name but refusing to fire when the records were added or removed. Currently there is no other way to intercept those messages except writing a plugin. Or is there?
Well, plugin is still required but we don’t have to write anything because we can use webhooks.
- Create a solution in your CDS environment to hold the flow.
- Create and save a skeleton for a flow with HTTP Request trigger. This is required to get an endpoint for HTTP Request trigger that we are going to use in the webhook.
- Register new webhook using that endpoint. When creating the webhook, all query parameters would need to be moved. Dont’ forget to replace %2F with / in sp parameter.
- Add steps for Associate and Disassociate. Asynchronous post-operation.
Entity filtering is not supported on these messages so you will have to listen for all of them. - The flow will now fire every time when a record is associated or disassociated. Hooray!
But what is the message coming with that HTTP request? Simple, it’s serialized RemoteExecutionObject. I wish the developer who was responsible for sending this object to the webhook knew about UseSimpleDictionaryFormat property and we wouldn’t have to deal with
"InputParameters": [
{
"key": "Target",
"value": {
"__type": "EntityReference:http://schemas.microsoft.com/xrm/2011/Contracts",
"Id": "6bcf8d45-9ff1-404a-827e-efc5c668f813",
"KeyAttributes": [],
"LogicalName": "adx_webrole",
"Name": null,
"RowVersion": null
}
},
{
"key": "Relationship",
"value": {
"__type": "Relationship:http://schemas.microsoft.com/xrm/2011/Contracts",
"PrimaryEntityRole": 0,
"SchemaName": "adx_webrole_contact"
}
}
then we would have had this instead:
"InputParameters": {
"Target": {
"__type": "EntityReference:http://schemas.microsoft.com/xrm/2011/Contracts",
"Id": "6bcf8d45-9ff1-404a-827e-efc5c668f813",
"KeyAttributes": [],
"LogicalName": "adx_webrole",
"Name": null,
"RowVersion": null
},
"Relationship": {
"__type": "Relationship:http://schemas.microsoft.com/xrm/2011/Contracts",
"PrimaryEntityRole": 0,
"SchemaName": "adx_webrole_contact"
}
}
and would have simply used expressions like triggerBody()['InputParameters']?['Target']?['LogicalName']
or triggerBody()['InputParameters']?['Relationship']?['SchemaName']
.
Until then, we have to create loops to extract values for the SchemaName of the relationship because that’s what you’d want to filter on when deciding if the message is for you. But dealing with horrendous serialization is a separate conversation.
Cover image courtesy of chem.libretexts.org / CC BY-SA.
From the description: “If the solvent is nucleophilic enough then the solvent becomes part of the overall mechanism. If it isn’t then only the incoming ligand becomes part of the mechanism.”
Of course.