Utiliser des webhooks pour créer des gestionnaires externes pour les événements de serveur

À partir des applications Dynamics 365 for Customer Engagement version 9.0, vous pouvez envoyer des données sur les événements qui se produisent sur le serveur à une application Web à l’aide de webhooks. Une webhook est un protocole HTTP léger permettant de connecter des API web et des services avec un modèle de publication/abonnement. Les expéditeurs de webhooks avertissent les destinataires à propos d’événements en adressant aux points de terminaison du destinataire des demandes comportant certaines informations sur les événements.

Les webhooks permettent aux développeurs et aux éditeurs de logiciels indépendants d’intégrer des données issues de Customer Engagement dans leur propre code personnalisé hébergé sur des services externes. Grâce au modèle webhooks, vous pouvez sécuriser votre point de terminaison à l’aide d’un en-tête d’authentification ou de clés de paramètre de chaîne de requête. Cette méthode est plus simple que le modèle d’authentification SAS que vous utilisez peut-être actuellement pour l’intégration de Azure Service Bus.

Au moment de faire votre choix entre le modèle webhook et l’intégration de Azure Service Bus, voici quelques éléments pour fonder votre réflexion :

  • Azure Service Bus fonctionne pour le traitement à grande échelle et offre un mécanisme complet de mise en file si Dynamics 365 envoie beaucoup d’événements.
  • Les webhooks ne peuvent évoluer que jusqu’au point auquel votre service Web hébergé peut gérer les messages.
  • Les webhooks permettent des étapes synchrones et asynchrones. Azure Service Bus autorise uniquement les étapes asynchrones.
  • Les webhooks envoient des requêtes POST avec une charge utile JSON et sont consommables par n’importe quel langage de programmation ou application Web hébergée n’importe où.
  • Il est possible d’appeler aussi bien les webhooks que Azure Service Bus à partir d’une activité de workflow personnalisée ou d’un plug-in.

Pour commencer

L’utilisation des webhooks comprend trois parties :

  • la création ou la configuration d’un service pour traiter les requêtes de webhook ;
  • une étape d’inscription du webhook sur le service Dynamics 365, ou
  • l’appel d’un webhook à partir d’un plug-in ou d’une activité de workflow personnalisée.

Cette rubrique commence par expliquer comment inscrire un webhook et tester l’inscription à l’aide d’un site de journalisation des requêtes. Vous disposerez des informations nécessaires sur les exigences relatives à la création et la configuration d’un service conçu pour traiter les demandes de webhook, décrites dans Créer ou configurer un service pour traiter les requêtes de webhook.

Inscrire un webhook

Utilisez l’outil Plug-in Registration Tool pour inscrire un webhook. Pour obtenir l’outil Plug-in Registration Tool, voir Outils de développement Dataverse.

L’outil Plug-in Registration Tool présente une nouvelle option Inscrire nouveau webhook à sélectionner.

Affiche l’option de menu pour enregistrer un nouveau webhook. Le raccourci clavier est Ctrl+W.

Lorsque vous inscrivez un webhook, vous devez fournir trois informations :

Élément Description
Nom Un nom unique décrivant le webhook.
URL du point de terminaison URL L’URL sur laquelle publier les informations du contexte d’exécution.
Authentification Une des trois options d’authentification. Pour chaque type d’authentification, vous devez fournir les clés qui identifieront la requête comme légitime.

Options d’authentification

L’option et les valeurs correctes d’authentification de l’inscription du webhook dépendent des attentes du point de terminaison. Le propriétaire du point de terminaison doit vous indiquer qu’utiliser. Pour utiliser des webhooks avec Dynamics 365, le point de terminaison doit autoriser une des trois options d’authentification décrites ci-dessous :

Type Description
HttpHeader comprend une ou plusieurs paires clé-valeur dans l’en-tête de la requête HTTP.
Exemple :
Key1: Value1
Key2: Value2
WebhookKey Inclut une chaîne de requête utilisant code comme clé et une valeur requise par le point de terminaison. Lorsque vous enregistrez le webhook à l’aide de l’outil Plug-in Registration, entrez uniquement la valeur.
Exemple :
?code=00000000-0000-0000-0000-000000000001
HttpQueryString comprend une ou plusieurs paires clé-valeur comme paramètres de chaîne de requête.
Exemple :
?Key1=Value1&Key2=Value2

Note

L’option WebhookKey est utile avec les Fonctions Azure car la chaîne de requête d’authentification doit comporter un nom de clé code.

Une requête adressée au point de terminaison configuré doit échouer lorsque les options d’authentification passées dans la requête ne correspondent pas. Cela relève du point de terminaison.

Inscriptions de webhook de requête

Les inscriptions de webhook sont stockées dans l’Entité ServiceEndpoint et ont une valeur Contrat de 8.

Vous pouvez obtenir des détails sur les webhooks inscrits en interrogeant l’entité ServiceEndpoint.

API web :

GET [organization URI]/api/data/v9.1/serviceendpoints?$filter=contract eq 8&$select= serviceendpointid,name,authtype,url

FetchXml:

<fetch>
  <entity name="serviceendpoint" >
    <attribute name="serviceendpointid" />
    <attribute name="name" />
    <attribute name="authtype" />
    <attribute name="url" />
    <filter>
      <condition attribute="contract" operator="eq" value="8" />
    </filter>
  </entity>
</fetch> 

Les détails des valeurs d’authentification définies se trouvent dans la propriété AuthValue et ne sont pas récupérables.

Inscrire une étape pour un webhook

Inscrire une étape pour un webhook est semblable à inscrire une étape pour un plug-in. La principale différence est qu’il est impossible de spécifier des informations de configuration.

Comme un plug-in, vous spécifiez le message et les informations sur les entités le cas échéant. Vous pouvez également spécifier où exécuter webhook dans le pipeline d’événement, le mode d’exécution et s’il faut supprimer les objets AsyncOperation lorsque l’opération aboutit.

Dialogue d’inscription de plug-in pour inscrire une nouvelle étape de webhook.

Les informations sur Nom de l’étape, et la Description sont remplies automatiquement en fonction des options de votre choix, mais vous pouvez les modifier. Si vous ne définissez aucun Attributs de filtrage pour un message qui les prend en charge, vous serez invité à le faire dans le cadre des meilleures pratiques de performance.

Mode d’exécution et débogage de votre inscription de webhook

Votre choix d’inscription de webhook modifie votre expérience au moment du débogage si tout ne fonctionne pas bien.

Mode asynchrone

Lorsque vous utilisez le mode d’exécution asynchrone, une tâche d’opération asynchrone est créée pour capturer la réussite ou l’échec de l’opération. Choisir de supprimer l’opération asynchrone quand elle aboutit vous fait économiser de l’espace de base de données.

Toutes les erreurs qui se produisent sont enregistrées dans les tâches système. Dans l’application web vous pouvez accéder à Paramètres > Système > Tâches système pour afficher l’état de tous les webhooks. Il s’y trouve une valeur de Raison du statut Échec. Ouvrez l’entité de la tâché système en échec pour voir les détails qui décrivent pourquoi la tâche a échoué.

Mode synchrone

Lorsque vous choisissez d’utiliser un mode d’exécution synchrone, toute défaillance est signalée à l’utilisateur de l’application par un dialogue d’erreur Point de terminaison non disponible informant l’utilisateur que le point de terminaison du service de webhook peut être configurée incorrectement ou n’est pas disponible. Cette boîte de dialogue vous permet de télécharger un fichier journal pour avoir des détails sur les erreurs.

Note

Vous devez utiliser le mode synchrone lorsqu’il est important que l’opération déclenchée par le webhook se produise immédiatement ,ou si vous souhaitez que la transaction entière échoue si la charge utile du webhook n’est pas reçue par le service. L’inscription simple d’une étape webhook fournit des options limitées pour gérer les échecs, mais vous pouvez également appeler des webhooks en utilisant des activités de workflow de plug-in s’il vous faut davantage de contrôle. Informations complémentaires : Appeler un webhook à partir d’un plug-in ou d’une activité de workflow.

Causes possibles de défaillance

les webhooks sont assez simples. Le service envoie la requête et évalue la réponse. Le système ne peut pas analyser les données renvoyées avec le corps de la réponse, il se contente de regarder la valeur du StatusCode de la réponse.

Le délai d’attente est de 60 secondes. En général, si aucune réponse n’est renvoyée avant le délai d’expiration ou si la valeur StatusCode de la réponse n’est pas dans la plage 2xx qui indique la réussite, la requête échoue. Il y a une exception lorsque l’erreur renvoyée est dans le tableau suivant :

StatusCode Description
502 Passerelle incorrecte
503 Service indisponible
504 Délai d’expiration de passerelle

Ces erreurs indiquent un problème de réseau qui peut être résolu lors d’une autre tentative. Le service du webhook n’effectue de nouvelle tentative que si ces codes d’erreur sont renvoyés.

Voir Tâches asynchrones de requête échouées pour une étape donnée pour savoir comment récupérer les données sur les tâches asynchrones échouées.

Étapes de requêtes inscrites pour un webhook

Les données des webhooks inscrits sont dans l’Entité SdkMessageProcessingStep.

Vous pouvez interroger les étapes inscrites pour un webhook spécifique lorsque vous connaissez l’ID serviceendpointid du webhook. Voir Inscriptions de webhook de requête pour une requête d’obtention de l’ID d’un webhook inscrit.

API web :

Vous pouvez utiliser cette requête d’API web où <id> est le ServiceEndpointId du webhook :

GET [organization URI]/api/data/v9.1/serviceendpoints(@id)/serviceendpoint_sdkmessageprocessingstep?$select=sdkmessageprocessingstepid,name,description,asyncautodelete,filteringattributes,mode,stage?@id=<id>

Pour plus d’informations sur l’étape inscrite, vous pouvez utiliser cette requête d’API web où <stepid> est le SdkMessageProcessingStepId de l’étape :

GET [organization URI]/api/data/v9.1/sdkmessageprocessingsteps(@id)?$select=name,description,filteringattributes,asyncautodelete,mode,stage&$expand=plugintypeid($select=friendlyname),eventhandler_serviceendpoint($select=name),sdkmessagefilterid($select=primaryobjecttypecode),sdkmessageid($select=name)?@id=<stepid>

FetchXML :

Vous pouvez utiliser ce FetchXML pour obtenir les mêmes informations en une requête où <serviceendpointid> représente l’ID du webhook :

<fetch>
  <entity name="sdkmessageprocessingstep" >
    <attribute name="name" />
    <attribute name="filteringattributes" />
    <attribute name="stage" />
    <attribute name="asyncautodeletename" />
    <attribute name="description" />
    <attribute name="mode" />
    <link-entity name="serviceendpoint" from="serviceendpointid" to="eventhandler" link-type="inner" alias="endpnt" >
      <attribute name="name" />
      <filter>
        <condition attribute="serviceendpointid" operator="eq" value="<serviceendpointid>" />
      </filter>
    </link-entity>
    <link-entity name="sdkmessagefilter" from="sdkmessagefilterid" to="sdkmessagefilterid" link-type="inner" alias="fltr" >
      <attribute name="primaryobjecttypecode" />
    </link-entity>
    <link-entity name="sdkmessage" from="sdkmessageid" to="sdkmessageid" link-type="inner" alias="msg" >
      <attribute name="name" />
    </link-entity>
  </entity>
</fetch>

Tâches asynchrones de requête échouées pour une étape donnée

Lorsque vous connaissez sdkmessageprocessingstepid d’une étape donnée, vous pouvez interroger l’Entité AsynchronousOperations sur toutes les erreurs. Vous pouvez utiliser la valeur OwningExtensionId pour filtrer les résultats pour une étape inscrite particulière. Les exemples suivants utilisent le <stepid> pour le sdkmessageprocessingstepid de l’étape.

API web :

GET [organization URI]/api/data/v9.1/asyncoperations?$orderby=completedon desc&$filter=statuscode eq 31 and _owningextensionid_value eq @stepid&$select=name,friendlymessage,errorcode,message,completedon?@stepid=<stepid>

FetchXML :

<fetch>
  <entity name="asyncoperation" >
    <attribute name="name" />
        <attribute name="friendlymessage" />
    <attribute name="errorcode" />
    <attribute name="message" />
    <attribute name="completedon" />     
    <filter>
      <condition attribute="owningextensionid" operator="eq" value="<stepid>" />
    </filter>
    <order attribute="completedon" descending="true" />
  </entity>
</fetch>

Tester votre inscription avec un site de journalisation des requêtes

Avant de passer à la création ou à la configuration d’un service utilisant des webhooks, vous devez tester le type des données que le service recevra, de manière à savoir le type des données que vous devrez traiter. Pour ce faire, vous pouvez utiliser un sites de journalisation des requêtes. Pour les besoins de cet exemple, nous leur utiliserons RequestBin pour configurer une cible pour les requêtes de webhook. Effectuez les opérations suivantes :

  1. Accédez à https://requestbin.com/ et cliquez sur Créer un RequestBin.

  2. La page suivante indique une URL Bin telle que : https://<random string>.x.pipestream.net. Copiez cette URL.

  3. Utilisez le plug-in Outil d’inscription pour inscrire un nouveau webhook, comme décrit dans la rubrique Inscrire un webhook. Utilisez l’URL que vous avez copiée à l’étape 2 comme URL du point de terminaison. Définissez un nom et toutes les propriétés d’authentification que vous souhaitez. RequestBin n’évaluera pas ces valeurs de la manière dont un vrai site traite les données, mais vous pourrez voir comment elles seront transmises.

  4. Utilisez le plug-in Outil d’inscription pour inscrire une étape à l’aide du webhook créé à l’étape 3, comme décrit dans Inscrire une étape pour un webhook. Veillez à utiliser un événement que vous pouvez facilement effectuer en modifiant des données dans l’application Dynamics 365, comme la mise à jour d’une entité de contact.

  5. Utilisez l’application Dynamics 365 pour effectuer l’opération de déclenchement de l’événement.

  6. Après avoir déclenché l’événement, retournez à la page RequestBin de l’étape 2. Vous devez voir une page similaire à celle-ci :

    Exemple de requête journalisée sur le site web RequestBin.

Note

Les résultats affichés sur ce site ne représentent pas nécessairement l’emploi correct des majuscules des valeurs envoyées. Les en-têtes HTTP ne sont pas sensibles à la casse et le site RequestBin applique une certaine mise en forme pour faciliter la lecteur des valeurs. Toutefois, les valeurs envoyées par Dynamics 365 sont toutes en minuscules, indépendamment de ce qui est affiché ici. Pour plus d’informations, voir : Données d’en-tête

Cet exemple montre comment les données passées dans la requête de webhook pour la mise à jour d’un contact où le webhook est inscrit pour transmettre des paires clé-valeur d’authentification HttpHeader :

Key Value
X-Test1 test1
X-Test2 test2

Les données du contexte d’exécution se trouvent sous la forme d’une chaîne JSON dans la section CORPS BRUT au bas de l’entrée. Il s’agit des données que le service web qui traite la requête de webhook doit évaluer. Pour pus d’informations, voir : Corps de la requête

Créer ou configurer un service pour traiter les requêtes de webhook

Les webhooks sont simplement un modèle utilisable dans un large éventail de technologies. Ils ne requièrent aucun framework, plateforme ou langage de programmation particulier. Utilisez vos compétences et vos connaissances pour fournir la solution appropriée. Les Fonctions Azure fournissent un excellent moyen de développement d’une solution à l’aide de WebHooks, mais ce n’est pas obligatoire. Cette section ne fournit pas d’instructions par rapport à une solution spécifique, mais décrit plutôt les données qui seront transmises à votre service et lui permettront d’être utile.

Comme montré dans la section Tester votre inscription avec un site de journalisation des requêtes, vous pouvez inscrire une étape de webhook de test et utiliser le site de journalisation des requêtes pour recueillir les types de données spécifiques que votre application peut traiter.

Données transmises au service

Il existe trois types de données dans la requête : chaîne de requête, données d’en-tête et corps de requête.

Chaîne de requête

Le seul type de données qui sont transmises sous forme de chaîne de requête sont les valeurs d’authentification, si le webhook est configuré pour utiliser les options WebhookKey ou HttpQueryString, décrites dans Options d’authentification.

Données d’en-tête

Si vous choisissez l’option d’authentification HttpHeader, vous devrez utiliser les paire clé/valeur demandées par votre service.

Les autres données que vous pourrez voir transmises à votre service se trouvent dans le tableau ci-dessous :

Key Description de la valeur
x-request-id Identificateur unique de la requête
x-ms-dynamics-organization Nom du client qui envoie la requête
x-ms-dynamics-entity-name Nom logique de l’entité passée dans les données du contexte d’exécution.
x-ms-dynamics-request-name Nom de l’événement pour lequel le webhook a été inscrit.
x-ms-correlation-request-id Identificateur unique permettant de suivre tout type d’extension. Cette propriété est utilisée par la plateforme pour empêcher les boucles infinies. Dans la plupart des cas, cette propriété peut être ignorée. Cette valeur peut être utilisée pour travailler avec le support technique car elle peut servir à interroger la télémétrie afin de savoir ce qui s’est passé pendant toute l’opération.
x-ms-dynamics-msg-size-exceeded Ne l’envoyez que quand la charge utile HTTP dépasse les 256 Ko.

Corps de la requête

Le corps contient une chaîne représentant la valeur JSON d’une instance de la classe RemoteExecutionContext. Ce sont les mêmes données qui sont transférées aux intégrations du Service Bus Azure.

Le service que vous avez créé doit analyser ces données pour extraire les éléments d’informations appropriés pour que votre service assure sa fonction. Votre choix d’analyser ces données dépend de la technologie que vous utilisez et de vos préférences.

Important

En raison de certaines optimisations de Service Bus, il n’est pas recommandé aux développeurs .NET de désérialiser le corps de la demande de message au format JSON en un objet RemoteExecutionContext. En revanche, utilisez JObject pour analyser le corps du message.

Ce qui suit est un exemple de données JSON sérialisées passées pour une étape inscrite avec les propriétés suivantes :

Propriété Description
Message Mettre à jour
Entité principale contact
Entité secondaire Aucun(e)
Filtrage d’attributs prénom, nom
Exécuter dans le contexte utilisateur Utilisateur appelant
Ordre d’exécution 1
Phase d’exécution dans le pipeline d’événement PostOperation
Mode d’exécution Asynchrone

Dans cet exemple, le prénom du contact a été changé de « Jim « en « James ».

{
    "BusinessUnitId": "e2b9dd85-e89e-e711-8122-000d3aa2331c",
    "CorrelationId": "aaaa0000-bb11-2222-33cc-444444dddddd",
    "Depth": 1,
    "InitiatingUserId": "11bb11bb-cc22-dd33-ee44-55ff55ff55ff",
    "InputParameters": [{
        "key": "Target",
        "value": {
            "__type": "Entity:http:\/\/schemas.microsoft.com\/xrm\/2011\/Contracts",
            "Attributes": [{
                "key": "firstname",
                "value": "James"
            }, {
                "key": "contactid",
                "value": "6d81597f-0f9f-e711-8122-000d3aa2331c"
            }, {
                "key": "fullname",
                "value": "James Glynn (sample)"
            }, {
                "key": "yomifullname",
                "value": "James Glynn (sample)"
            }, {
                "key": "modifiedon",
                "value": "\/Date(1506384247000)\/"
            }, {
                "key": "modifiedby",
                "value": {
                    "__type": "EntityReference:http:\/\/schemas.microsoft.com\/xrm\/2011\/Contracts",
                    "Id": "11bb11bb-cc22-dd33-ee44-55ff55ff55ff",
                    "KeyAttributes": [],
                    "LogicalName": "systemuser",
                    "Name": null,
                    "RowVersion": null
                }
            }, {
                "key": "modifiedonbehalfby",
                "value": null
            }],
            "EntityState": null,
            "FormattedValues": [],
            "Id": "6d81597f-0f9f-e711-8122-000d3aa2331c",
            "KeyAttributes": [],
            "LogicalName": "contact",
            "RelatedEntities": [],
            "RowVersion": null
        }
    }],
    "IsExecutingOffline": false,
    "IsInTransaction": false,
    "IsOfflinePlayback": false,
    "IsolationMode": 1,
    "MessageName": "Update",
    "Mode": 1,
    "OperationCreatedOn": "\/Date(1506409448000-0700)\/",
    "OperationId": "4af10637-4ea2-e711-8122-000d3aa2331c",
    "OrganizationId": "00aa00aa-bb11-cc22-dd33-44ee44ee44ee",
    "OrganizationName": "OrgName",
    "OutputParameters": [],
    "OwningExtension": {
        "Id": "75417616-4ea2-e711-8122-000d3aa2331c",
        "KeyAttributes": [],
        "LogicalName": "sdkmessageprocessingstep",
        "Name": null,
        "RowVersion": null
    },
    "ParentContext": {
        "BusinessUnitId": "e2b9dd85-e89e-e711-8122-000d3aa2331c",
        "CorrelationId": "aaaa0000-bb11-2222-33cc-444444dddddd",
        "Depth": 1,
        "InitiatingUserId": "11bb11bb-cc22-dd33-ee44-55ff55ff55ff",
        "InputParameters": [{
            "key": "Target",
            "value": {
                "__type": "Entity:http:\/\/schemas.microsoft.com\/xrm\/2011\/Contracts",
                "Attributes": [{
                    "key": "firstname",
                    "value": "James"
                }, {
                    "key": "contactid",
                    "value": "6d81597f-0f9f-e711-8122-000d3aa2331c"
                }],
                "EntityState": null,
                "FormattedValues": [],
                "Id": "6d81597f-0f9f-e711-8122-000d3aa2331c",
                "KeyAttributes": [],
                "LogicalName": "contact",
                "RelatedEntities": [],
                "RowVersion": null
            }
        }, {
            "key": "SuppressDuplicateDetection",
            "value": false
        }],
        "IsExecutingOffline": false,
        "IsInTransaction": false,
        "IsOfflinePlayback": false,
        "IsolationMode": 1,
        "MessageName": "Update",
        "Mode": 1,
        "OperationCreatedOn": "\/Date(1506409448000-0700)\/",
        "OperationId": "4af10637-4ea2-e711-8122-000d3aa2331c",
        "OrganizationId": "00aa00aa-bb11-cc22-dd33-44ee44ee44ee",
        "OrganizationName": "OneFarm",
        "OutputParameters": [],
        "OwningExtension": {
            "Id": "75417616-4ea2-e711-8122-000d3aa2331c",
            "KeyAttributes": [],
            "LogicalName": "sdkmessageprocessingstep",
            "Name": null,
            "RowVersion": null
        },
        "ParentContext": null,
        "PostEntityImages": [],
        "PreEntityImages": [],
        "PrimaryEntityId": "6d81597f-0f9f-e711-8122-000d3aa2331c",
        "PrimaryEntityName": "contact",
        "RequestId": null,
        "SecondaryEntityName": "none",
        "SharedVariables": [{
            "key": "ChangedEntityTypes",
            "value": [{
                "__type": "KeyValuePairOfstringstring:#System.Collections.Generic",
                "key": "feedback",
                "value": "Update"
            }, {
                "__type": "KeyValuePairOfstringstring:#System.Collections.Generic",
                "key": "contract",
                "value": "Update"
            }, {
                "__type": "KeyValuePairOfstringstring:#System.Collections.Generic",
                "key": "salesorder",
                "value": "Update"
            }, {
                "__type": "KeyValuePairOfstringstring:#System.Collections.Generic",
                "key": "connection",
                "value": "Update"
            }, {
                "__type": "KeyValuePairOfstringstring:#System.Collections.Generic",
                "key": "socialactivity",
                "value": "Update"
            }, {
                "__type": "KeyValuePairOfstringstring:#System.Collections.Generic",
                "key": "postfollow",
                "value": "Update"
            }, {
                "__type": "KeyValuePairOfstringstring:#System.Collections.Generic",
                "key": "incident",
                "value": "Update"
            }, {
                "__type": "KeyValuePairOfstringstring:#System.Collections.Generic",
                "key": "invoice",
                "value": "Update"
            }, {
                "__type": "KeyValuePairOfstringstring:#System.Collections.Generic",
                "key": "entitlement",
                "value": "Update"
            }, {
                "__type": "KeyValuePairOfstringstring:#System.Collections.Generic",
                "key": "lead",
                "value": "Update"
            }, {
                "__type": "KeyValuePairOfstringstring:#System.Collections.Generic",
                "key": "opportunity",
                "value": "Update"
            }, {
                "__type": "KeyValuePairOfstringstring:#System.Collections.Generic",
                "key": "quote",
                "value": "Update"
            }, {
                "__type": "KeyValuePairOfstringstring:#System.Collections.Generic",
                "key": "socialprofile",
                "value": "Update"
            }, {
                "__type": "KeyValuePairOfstringstring:#System.Collections.Generic",
                "key": "contact",
                "value": "Update"
            }]
        }],
        "Stage": 30,
        "UserId": "11bb11bb-cc22-dd33-ee44-55ff55ff55ff"
    },
    "PostEntityImages": [{
        "key": "AsynchronousStepPrimaryName",
        "value": {
            "Attributes": [{
                "key": "fullname",
                "value": "James Glynn (sample)"
            }, {
                "key": "contactid",
                "value": "6d81597f-0f9f-e711-8122-000d3aa2331c"
            }],
            "EntityState": null,
            "FormattedValues": [],
            "Id": "6d81597f-0f9f-e711-8122-000d3aa2331c",
            "KeyAttributes": [],
            "LogicalName": "contact",
            "RelatedEntities": [],
            "RowVersion": null
        }
    }],
    "PreEntityImages": [],
    "PrimaryEntityId": "6d81597f-0f9f-e711-8122-000d3aa2331c",
    "PrimaryEntityName": "contact",
    "RequestId": null,
    "SecondaryEntityName": "none",
    "SharedVariables": [],
    "Stage": 40,
    "UserId": "11bb11bb-cc22-dd33-ee44-55ff55ff55ff"
}

Important

Lorsque la taille de la charge utile HTTP dépasse 256 Ko, l’en-tête x-ms-dynamics-msg-size-exceeded est inclus et les propriétés RemoteExecutionContext suivantes sont supprimées :

Certaines opérations ne comprennent pas ces propriétés.

Appeler un webhook à partir d’un plug-in ou d’une activité de workflow

Comme un webhook est un type de point de terminaison de service, vous pouvez également l’appeler sans inscrire d’étape avec un plug-in ou une activité de workflow, de la même manière que vous pouvez le faire pour un point de terminaison Azure Service Bus. Vous devez indiquer l’ID ServiceEndpointId à l’interface IServiceEndpointNotificationService. Pour plus d’informations, voir les exemples Azure Service Bus suivants :

Voir aussi

Étendre Customer Engagement sur le serveur
Écrire des plug-ins pour étendre les processus d’entreprise
Automatiser vos processus d’entreprise dans Customer Engagement (on-premises)
Service asynchrone dans Dynamics 365 Customer Engagement (on-premises)
Extensions Azure pour Dynamics 365 Customer Engagement (on-premises)
Exemple : Plug-in personnalisé compatible Azure
Exemple : Activité de workflow personnalisée compatible Azure
Fonctions Azure
Entité ServiceEndpoint
Entité SdkMessageProcessingStepBase
Entité AsynchronousOperations
RemoteExecutionContext
IServiceEndpointNotificationService