Home / Nieuws / Gebruik webhooks om cloud flows aan te roepen
2 september 2022
Door: Wilmer Alcivar

Gebruik webhooks om cloud flows aan te roepen

Uitgelichte afbeelding voor Blog over webhooks gebruiken om cloud flows aan te roepen

De business requirement

Vorige week had ik een business requirement over het uitvoeren van aangepaste logica, maar alleen wanneer het verkoopkans-record van “in beoordeling” naar “goedgekeurd” gaat, in elk ander scenario mag de logica niet worden uitgevoerd.

Om aan deze vereiste te voldoen wilde ik een plug-in gebruiken met een pre- en een post-afbeelding, maar toen bedacht ik me: wat als ik dit kan doen met een meer “low code” -benadering? Toen herinnerde ik me webhooks!

Voordat ik verder ga, wil ik beginnen met te vragen; wat we weten over webhooks?

Volgens de definitie van de Microsoft-documentatie staat dat “CRM Webhooks een lichtgewicht HTTP-patroon is voor het verbinden van web-API’s en -services met een publicatie-/abonneermodel”

Met andere woorden, dit betekent dat dit een functie is waarmee we een externe API of zelfs onze eigen service kunnen aanroepen met behulp van een HTTP-verzoek door deze te koppelen aan een gebeurtenis die plaatsvindt in Dataverse, zoals het maken, bijwerken of zelfs verwijderen van een record.

Webhooks zijn aanwezig in Dynamics 365 CE-wereld sinds versie 9.0, eind 2017, maar ik denk dat ze niet zo veel worden gebruikt. Ik heb deze functie bijvoorbeeld een paar keer gebruikt in echte projecten sinds 2019.

Maar ondanks dat zijn er verschillende berichten in de community over het aanroepen van een Azure-functie of een cloud flow met behulp van webhooks. Maar zoals ik al eerder zei, wat als ik hetzelfde kan doen als ik zou kunnen doen met behulp van een plug-in, maar dan in combinatie van een cloudflow met een webhook die de pre- en post-afbeeldingen naar de flow stuurt? Uiteindelijk wilde ik de voor- en nadelen weten van het gebruik van de ene optie boven de andere.

Om te beginnen wil ik vermelden dat er twee punten zijn waar we rekening mee moeten houden als we een webhook willen maken:

  • Ten eerste moeten we een service hebben (een externe API of Azure-functie of in dit geval een cloudflow die ik ga gebruiken).
  • Dan moeten we de webhook maken/registreren met behulp van de plug-in registratietool, ja, onze geliefde tool waarmee we plug-ins en workflow activiteiten kunnen registreren.

Laten we nu verder gaan met het eerste punt.

Een cloudstroom maken

Als we een cloudflow van een webhook willen aanroepen, moet de trigger van de flow een ​​http-verzoek zijn:

De volgende actie kan een samenstellingsactie zijn, dit is een tijdelijke actie om twee redenen, één omdat een flow naast de trigger een extra actie moet hebben om deze op te slaan, en ook omdat we willen zien wat de flow ontvangt van webhook.

Voor nu is dat genoeg voor de flow, we gaan later verder. Nu moet je voor het tweede punt gaan, namelijk het maken van de webhook.

Een webhook maken

Hiervoor moeten we de plug-in registratietool gebruiken, deze kan XRMToolbox gebruiken of de officiële van Microsoft. Nadat we zijn verbonden met de omgeving, kunnen we een nieuwe webhook maken:

Vervolgens moeten we de webhook een naam geven, en ik zou je graag een aanbeveling geven over deze stap. Voeg een beschrijvende naam toe die de webhook identificeert. In het URL-vak moeten we de URL plaatsen die beschikbaar is in de flow trigger, dus we moeten teruggaan naar de flow en de URL van de trigger kopiëren:

Voordat je het in Webhook plakt, plak je het eerst in een kladblokbestand of welke bestandseditor je ook hebt, want niet alle URL’s zouden in het URL-vak moeten staan. De parameters zouden niet in dat deel moeten staan, en als ik zeg parameters, verwijs ik naar de queryparameters. Dat wil zeggen alles na het ‘?’ karakter. In het volgende voorbeeld zijn de parameters api-version, sp, sv en sig:

Dus wat we in het URL-vak moeten plaatsen, is wat is gespecificeerd tot aan het aanroepende woord. Daarnaast is het ook belangrijk om te vermelden dat we de‘%2F-tekens moeten vervangen door het / teken in de parameter met de naam sp. Aan het einde moet die parameter moet deze waarde hebben:

sp=/triggers/manual/run

Een goed hulpmiddel om het laatste deel te doen zou ook kunnen zijn: https://meyerweb.com/eric/tools/dencoder/ kopieer en plak gewoon de stroom-URL en deze tol zal alle %2F vervangen door /

Nadat we klaar zijn met het configureren van de webhook en voordat we de parameters toevoegen, moeten we de optie “HttpQueryString” selecteren in het vak Verificatie. Uiteindelijk zou de configuratie iets moeten zijn dat lijkt op:

Klik op de knop Opslaan en nu moeten we de stap toevoegen, net zoals wanneer we een stap voor een plug-in toevoegen:

Zoals ik in het begin al zei, was de vereiste dat ik een logica alleen moest laten uitvoeren wanneer het verkoopkans-record van de status “in beoordeling” naar “goedgekeurd” gaat, dus de stap zou in het bericht Update moeten staan ​​en de entiteit zou de kans moeten zijn. Het is belangrijk om te vermelden dat ik de oude en nieuwe waarde van het ‘status reason field’ wil, dus we moeten een PreImage en een PostImage instellen, en om dat te doen moet de stap een PostOperation zijn:

Na het registreren van de stap, is de volgende actie om de PreImage en PostImage toe te voegen:

Eerst registreren we de PreImage en zorgen we ervoor dat je alleen het veld of de velden registreert die je nodig hebt. Verstuur niet alle velden omdat het de flow langer zal laten duren om te voltooien, en in sommige scenario’s zorgt het ervoor dat de flows twee keer worden geactiveerd:

Hetzelfde geldt voor de PostImage, dus uiteindelijk zou de configuratie van de webhook zoiets moeten zijn als:

Nu kunnen we een test maken om de statusreden van de opportunity binnen de model driven app bij te werken:

Klik op opslaan en laten we het flow execution log bekijken:

Ik raad aan om de uitvoer van de compose-action te kopiëren en in een bestandseditor zoals visual studiocode te plakken, omdat je eerst de structuur moet begrijpen van de JSON die naar de cloudflow is verzonden:

Zoals we in de bovenstaande afbeelding kunnen zien, is de JSON vrij groot en kunnen we de structuur voor de PreImage en PostImage zien waar de oude en nieuwe waarden van het status reason field zich bevinden.

Dus om beide waarden te krijgen, moeten we twee expressies maken waarvan ik denk dat ze altijd hetzelfde zijn als we de oude en de nieuwe waarde van een veld willen krijgen, maar voor het geval je ze eerder kunt controleren, in mijn geval zijn dit de twee uitdrukkingen: 

triggerBody()?[‘PreEntityImages’]?[0]?[‘value’]?[‘FormattedValues’]?[0]?[‘value’]

triggerBody()?[‘PostEntityImages’]?[0]?[‘value’]?[‘FormattedValues’]?[0]?[‘value’]

 

De eerste expressie retourneert de oude waarde en de tweede retourneert de nieuwe waarde van het veld.

En als we deze uitdrukkingen in variabelen binnen de flow plaatsen, ziet het er als volgt uit:

Vervolgens moeten we een voorwaarde-actie toevoegen om de PreValue en PostValue te valideren, als de validatie correct is, kunnen we de aangepaste logica toepassen:

Nu kunnen we onze laatste test doen, dus laten we de kans grijpen en het status reason field opnieuw bijwerken:

Klik op opslaan en laten we het flow execution log bekijken:

Nu hebben we de oude waarde en de nieuwe waarde van een veld met een meer “low code” -benadering.

Scenario’s waarin het kan worden toegepast

Ik weet zeker dat er nog veel meer scenario’s zijn waarin we op deze manier webhooks kunnen combineren met cloudflows

Een ander voorbeeld kan zijn dat wanneer een record wordt verwijderd, we een trace of log willen maken over het verwijderde record. Als we een normale cloudflow gebruiken wanneer het record wordt verwijderd, is de enige informatie die we krijgen de ID, er worden geen gegevens meer aan ons verstrekt. Maar als we een webhook gebruiken met een PreOperation-stap en een PreImage, dan kunnen we alle informatie over het verwijderde record krijgen.

Dus de Webhook-configuratie is hetzelfde, maar gebruikt natuurlijk een andere cloudflow, voeg vervolgens de PreOperation-stap toe en vervolgens de PreImage:

De PreOperation stap:

En de PreImage, let er nogmaals op dat je alleen de velden toevoegt die je nodig hebt:

En als we een opportunity verwijderen, zien we de volgende flow execution log:

In dit geval heb ik op elke actie-iteratie de volgende uitdrukking toegepast:

triggerBody()?[‘PreEntityImages’]?[0]?[‘value’]?[‘FormattedValues’]

En binnen de opstelactie deze twee uitdrukkingen om de naam van het veld en de waarde ervan te zien:

items(‘Apply_to_each’)?[‘key’] : items(‘Apply_to_each’)?[‘value’]

Ik deed dit omdat ik alle velden wilde krijgen die ik in de PreImage had verzonden.

Een ander voorbeeld zou kunnen zijn om de logica alleen uit te voeren wanneer de BPF van fase A naar fase B gaat, in welk geval de webhook-stap moet worden gekoppeld aan de overeenkomstige BPF-tabel:

En nogmaals, in dit geval moeten we een PreImage en een PostImage toevoegen, de rest is hetzelfde.

 

Webhook + Flow of plug-in?

Met het Power Platform hebben we veel features gekregen die elkaar overlappen. Ik denk dat alle functionaliteiten van CRM Webhooks in combinatie met Flows in een plug-in kan worden gedaan. Dus hier zijn de voor- en nadelen naar mijn mening:

  • WebHooks in combinatie met Flows is een low-code benadering. Ik geloof dat een functionele gebruiker dit kan, misschien zullen ze een beetje worstelen met de expressies in de Cloud flow, maar verder denk ik dat het een goede manier is om een vereiste te krijgen met behulp van deze methode.
  • Voor de plug-in weten we al dat het een pro-code-aanpak is, en natuurlijk hebben we vrije ruimte om zoveel aan te passen als we willen. Naar mijn mening is er geen regel die zegt, gebruik altijd de ene optie boven de andere, het is namelijk afhankelijk van de vereiste/business case. Bijvoorbeeld als we het hebben over het toepassen van aangepaste logica op een grote set records, geef ik de voorkeur aan een snellere manier om het te doen met behulp van een plug-in of zelfs een Azure-functie.
  • De nadelen van webhooks met Flows zijn het gebrek aan manieren om met fouten om te gaan. Als we bijvoorbeeld een webhook maken met een pre-op-synchronisatiestap, dan willen we iets binnen de cloudflow valideren, bijvoorbeeld een waarde in een veld. Als de waarde niet correct is, willen we een fout tonen aan de gebruiker, alleen kunnen we dat niet doen. De bewerking wordt effectief geannuleerd en een algemene foutmelding wordt weergegeven aan de gebruiker. Maar dat is het dan ook. Naar mijn mening is dat geen goede gebruikerservaring om een ​​generieke fout te zien en zonder te weten waarom de update-bewerking wordt geannuleerd.
  • En voor de nadelen van de plug-in kunnen we zeggen dat deze moet worden gecodeerd, dus misschien kost het meer tijd om de oplossing te bouwen. En we kunnen ook de maximale looptijd van 2 minuten noemen.

Conclusie

  • Zoals we hebben gezien, is het een low-code-aanpak, we hoeven alleen maar een cloudflow te creëren en de webhook te registreren en dat is alles. Nogmaals, het moeilijkste zijn de uitdrukkingen in de cloudflow om de waarden te krijgen.
  • Met behulp van de registratietool voor plug-ins kunnen we de gebeurtenis voor het maken, bijwerken of verwijderen aan onze cloudflow koppelen.
  • Het is belangrijk om afbeeldingen te gebruiken, het kunnen pre- of post-afbeeldingen zijn om de juiste waarden binnen de wolkenstroom te krijgen.
  • Als een cloudflow wordt gebruikt, houd er dan rekening mee dat we de expressies moeten maken om de waarden te krijgen, triggerBody + vraagteken + vierkante haken met de naam van het attribuut + …
  • Persoonlijk zou ik deze aanpak aanbevelen als we een scenario hebben zoals ik eerder heb opgemerkt. Maar als we onmiddellijk enige logica moeten toepassen en als we een bericht aan de gebruiker moeten tonen, dan raad ik deze aanpak niet aan. Hetzelfde geldt voor het toepassen van logica op een grote set records.
  • En wanneer je de plug-inregistratietool gebruikt om de webhook-stap te maken, neem dan niet alle velden op, analyseer eerst welke velden je naar de stroom wilt sturen, omdat het anders te lang kan duren voordat de cloudflow is voltooid en mogelijk tweemaal wordt uitgevoerd. Het overkwam mij toen ik contact- en accountzoekopdrachten gebruikte. Ik vermeed die twee en gebruikte in plaats daarvan het klantveld.

PS: Bedankt Victor Sijtsma voor het helpen met deze blogpost