Verwenden Sie Webhooks zum Erstellen externer Handler für Serverereignisse

Mit Microsoft Dataverse können Sie Daten zu Ereignissen senden, die auf dem Server für eine Webanwendung mit Webhooks auftreten. Webhooks ist ein einfaches HTTP-Muster zur Verbindung von Web-APIs und -diensten mit einem Veröffentlichungs-/Abonnementmodell. Webhook-Absender benachrichtigen Empfänger über Ereignisse, indem sie Anfragen mit einigen Informationen zu den Ereignissen an Empfängerendpunkte senden.

Mit Webhooks können Entwickelnde und ISVs Dataverse-Daten in ihren eigenen benutzerdefinierten Code integrieren, der auf externen Diensten gehostet wird. Wenn Sie das WebHook-Modell verwenden, können Sie Ihren Endpunkt durch die Verwendung von Authentifizierungs-Header- oder Query-String-Parameter-Schlüsseln absichern. Dies ist einfacher als das SAS-Authentifizierungsmodell, das Sie derzeit möglicherweise für die Azure Service Bus-Integration verwenden.

Wenn Sie sich zwischen dem WebHook-Modell und der Azure Service Bus-Integration entscheiden, sollten Sie einige Elemente im Auge behalten:

  • Azure Service Bus eignet sich für die hochskalierte Verarbeitung und bietet einen vollständigen Abfragemechanismus, wenn Dataverse viele Ereignisse weiterleitet.
  • Webhooks können nur bis zu dem Punkt skaliert werden, an dem Ihr gehosteter Webdienst die Nachrichten verarbeiten kann.
  • Webhooks ermöglicht synchrone und asynchrone Schritte. Azure Service Bus ermöglicht nur asynchrone Schritte.
  • Webhooks senden POST-Anforderungen mit JSON-Nutzlast und können von allen Programmiersprachen oder Webanwendungen an jedem beliebigen Ort konsumiert werden.
  • Sowohl Webhooks als auch Azure Service Bus können über ein Plug-In oder eine angepasste Workflowaktivität aufgerufen werden.

Los geht's

Die Verwendung von Webhooks besteht aus drei Teilen:

  • Erstellen oder Konfigurieren eines Dienstes, um WebHook-Anfragen zu konsumieren.
  • Registrieren des WebHook-Schrittes auf dem Dataverse-Dienst, oder
  • Aufrufen eines WebHooks von einem Plugin oder einer angepassten Workflow-Aktivität.

Beginnen Sie mit der Registrierung eines Test-WebHooks

Um zu verstehen, wie man einen Dienst erstellt und konfiguriert, um eine WebHook-Anfrage von Dataverse zu konsumieren, ist es sinnvoll, zunächst zu verstehen, wie man einen WebHook registriert. Weitere Informationen: Registrieren eines WebHooks

Wenn Sie einen Beispiel-WebHook registriert haben, können Sie eine Anfrageprotokollierungsseite verwenden, um die Kontextdaten zu untersuchen, die übergeben werden. Weitere Informationen: Test-WebHook-Registrierung mit Anforderungsprotokollierungsseite

Tipp

Wenn Sie die Schritte zur Registrierung eines Test-WebHooks und zur Untersuchung der übergebenen Kontextdaten durchführen, werden die restlichen Informationen in diesem Thema leichter verständlich. Führen Sie diese Schritte aus und kehren Sie zu diesem Thema zurück.

Erstellen oder Konfigurieren eines Dienstes zum Konsumieren von WebHook-Anfragen

Webhooks sind einfach ein Muster, das mit einer breiten Palette von Technologien angewendet werden kann. Es gibt keine erforderlichen Frameworks, Plattformen oder Programmiersprachen, die Sie verwenden müssen. Nutzen Sie Ihr Wissen und Ihre Fähigkeiten, um die entsprechende Lösung bereitzustellen.

Azure Functions bieten eine hervorragende Möglichkeit, eine Lösung mit Webhooks bereitzustellen, sind aber keine Voraussetzung. Dieser Abschnitt enthält keine Anweisungen für eine bestimmte Lösung, stattdessen werden die Daten beschrieben, die an Ihren Service übergeben werden, damit dem Service ein Wert hinzugefügt werden kann.

Wie in Test-WebHook-Registrierung mit Anforderungsprotokollierungsseite gezeigt, können Sie einen Test-WebHook-Schritt registrieren und die Anforderungsprotokollierungsseite verwenden, um die spezifischen Arten von Daten zu erfassen, die Ihre Anwendung verarbeiten kann.

An einen Service übergebene Daten

Es gibt drei Datentypen in der Anforderung: Abfragezeichenfolge, Header-Daten und Anforderungstext.

Abfragezeichenfolge

Die einzige Art von Daten, die als Query-String übergeben wird, können die übergebenen Authentifizierungswerte sein, wenn der WebHook so konfiguriert ist, dass er die Optionen WebhookKey oder HttpQueryString verwendet, wie in Authentifizierungsoptionen beschrieben.

Header-Daten

Wenn Sie die Authentifizierungsoption HttpHeader auswählen, müssen Sie die Schlüssel-Wert-Paare verwenden, die für den Service erforderlich sind.

Andere Daten, die möglicherweise an Ihren Service übergeben wurden, finden Sie in der untenstehenden Tabelle:

Schlüssel Wertbeschreibung
x-ms-dynamics-organization Der Domänenname der Umgebung, die die Anforderung sendet
x-ms-dynamics-entity-name Der logische Name der Tabelle, die in den Ausführungskontextdaten übergeben wird.
x-ms-dynamics-request-name Der Name des Ereignisses, für das der WebHook-Schritt registriert wurde.
x-ms-correlation-request-id Eindeutiger Bezeichner für die Verfolgung beliebiger Erweiterungstypen. Diese Eigenschaft wird von der Plattform zur Vorbeugung von Endlosschleifen verwendet. In den meisten Fällen kann diese Eigenschaft ignoriert werden. Dieser Wert wird möglicherweise verwendet, wenn Sie sich an den technischen Support wenden, da er zum Abfragen von Telementrie verwendet werden kann,um herauszufinden, was während der gesamten Operation passiert ist.
x-ms-dynamics-msg-size-exceeded Wird nur gesendet, wenn die Größe der HTTP-Nutzlast 256 KB übersteigt.

Anforderungstext

Der Text enthält die Zeichenfolge, die den JSON-Wert einer Instanz der RemoteExecutionContext-Klasse darstellt. Dies sind die gleichen Daten, die an Azure Service Bus-Integrationen übergeben werden.

Der Service, den Sie erstellen, muss diese Daten analysieren, um für Ihren Service die relevanten Informationen zu extrahieren, um dessen Funktion bereitzustellen. Die Art, wie Sie das Analysieren dieser Daten festlegen, hängt von Ihren Einstellungen und der verwendeten Technologie ab.

Im Folgenden finden Sie ein Beispiel serialisierter JSON-Daten, die für einen Schritt übergeben werden, der mit den folgenden Eigenschaften übergeben wird.

Eigenschaft Beschreibung
Meldung Update
Primäre Entität Kontakt
Sekundäre Entität Kein Wert
Filterattribute firstname,lastname
Im Kontext des Benutzers ausführen Aufrufender Benutzer
Ausführungsreihenfolge 1
Ereignis-Pipeline-Phase der Ausführung PostOperation
Ausführungsmodus Asynchron
{
    "BusinessUnitId": "e2b9dd85-e89e-e711-8122-000d3aa2331c",
    "CorrelationId": "b374239d-4233-41a9-8b17-a86cb4f737b5",
    "Depth": 1,
    "InitiatingUserId": "75c2dd85-e89e-e711-8122-000d3aa2331c",
    "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": "75c2dd85-e89e-e711-8122-000d3aa2331c",
                    "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": "4ef5b371-e89e-e711-8122-000d3aa2331c",
    "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": "b374239d-4233-41a9-8b17-a86cb4f737b5",
        "Depth": 1,
        "InitiatingUserId": "75c2dd85-e89e-e711-8122-000d3aa2331c",
        "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": "4ef5b371-e89e-e711-8122-000d3aa2331c",
        "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": "75c2dd85-e89e-e711-8122-000d3aa2331c"
    },
    "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": "75c2dd85-e89e-e711-8122-000d3aa2331c"
}

Wichtig

Wenn die Größe der gesamten HTTP-Nutzlast 256 KB übersteigt, wird der x-ms-dynamics-msg-size-exceeded-Header mit eingeschlossen und die folgenden RemoteExecutionContext-Eigenschaften werden entfernt:

Einige Operationen enthalten diese Eigenschaften nicht.

Aufrufen eines WebHooks von einem Plug-in oder einer Workflow-Aktivität

Da ein WebHook eine Art Service-Endpunkt ist, können Sie ihn auch aufrufen, ohne einen Schritt mit einem Plug-in oder einer Workflow-Aktivität zu registrieren, so wie Sie es für einen Azure Service Bus-Endpunkt tun können. Sie müssen die ServiceEndpointId für die IServiceEndpointNotificationService-Schnittstelle bereitstellen. Sehen Sie die folgenden Azure Service Bus-Beispiele, um weitere Informationen zu erhalten:

Fehlerbehebung bei WebHook-Registrierungen

Webhooks sind verhältnismäßig einfach. Der Service sendet die Anforderung und wertet die Antwort aus. Das System kann keine Daten analysieren, die mit dem Text der Antwort zurückgegeben werden, es wird nur ein Blick auf den Reaktionswert StatusCode geworfen

Das Timeout beträgt 60 Sekunden. Im Allgemeinen kommt es zu einem Misserfolg, wenn keine Antwort vor dem Timeout zurückgegeben wird oder wenn der Reaktionswert StatusCode nicht innerhalb des Bereiches 2xx ist, und so einen Erfolg anzeigt. Dies gilt nicht, wenn der zurückgegebene Fehler in folgender Tabelle enthalten ist:

StatusCode Beschreibung
502 Ungültiges Gateway
503 Dienst ist nicht verfügbar
504 Gateway-Timeout

Diese Fehler weisen auf ein Netzwerkproblem hin, das möglicherweise mit einem anderen Versuch aufgelöst werden kann. Der WebHook-Dienst wird nur dann einen weiteren Versuch unternehmen, wenn diese Fehlercodes zurückgegeben werden.

Asynchrone Webhooks

Wenn Ihr WebHook so registriert ist, dass er asynchron ausgeführt wird, können Sie den Systemauftrag auf Details zum Fehler untersuchen. Weitere Informationen: Bei der Abfrage kam es zu Fehlern bei asynchronen Aufträgen für einen bestimmten Schritt

Synchrone Webhooks

Wenn Sie den synchronen Ausführungsmodus verwenden, werden alle Fehler dem Benutzer der Anwendung gemeldet. Dazu wird ein Endpunkt nicht verfügbar-Fehlerdialog angezeigt, der den Benutzer darüber informiert, dass der Webhook-Service-Endpunkt möglicherweise falsch konfiguriert oder nicht verfügbar ist. Im Dialogfeld können Sie eine Protokolldatei mit Informationen zu etwaigen Fehlern herunterladen.

Hinweis

Jeder für einen synchronen Schritt registrierte Webhook sendet die Ausführungskontextdaten sofort an die konfigurierten Endpunkt. Wenn nach dem Senden der Anforderung ein Fehler auftritt, wird der Datenvorgang zurückgesetzt, die an den konfigurierten Endpunkt gesendete Anforderung kann jedoch nicht zurückgerufen werden.

Nächste Schritte,

Registrieren eines WebHooks
Test der WebHook-Registrierung mit der Website für die Anforderungsprotokollierung

Siehe auch

Schreiben eines Plug-Ins
Registrieren eines Plug-Ins
Asynchroner Service in Dataverse
Beispiel: Benutzerdefiniertes Azure-fähiges Plug-In
Beispiel: Azure-fähige benutzerdefinierte Workflowaktivität
Azure Functions
ServiceEndpunkt-Tabelle
SdkMessageProcessingStep-Tabelle
TabelleAsynchronousOperations
RemoteExecutionContext
IServiceEndpointNotificationService

Hinweis

Können Sie uns Ihre Präferenzen für die Dokumentationssprache mitteilen? Nehmen Sie an einer kurzen Umfrage teil. (Beachten Sie, dass diese Umfrage auf Englisch ist.)

Die Umfrage dauert etwa sieben Minuten. Es werden keine personenbezogenen Daten erhoben. (Datenschutzbestimmungen).