Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Use webhooks para enviar eventos de servidor do Microsoft Dataverse para um aplicativo Web externo. Este artigo explica os dados que o Dataverse envia nas solicitações e como os webhooks ajudam você a desenvolver manipuladores externos para eventos do servidor.
Usando webhooks, desenvolvedores e ISVs podem integrar dados do Dataverse com seu próprio código personalizado hospedado em serviços externos. O modelo de webhook permite que você proteja o ponto de extremidade usando um cabeçalho de autenticação ou chaves de parâmetros de sequência de caracteres de consulta. Essa abordagem é mais simples do que o modelo de autenticação SAS que você pode usar atualmente para a integração do Barramento de Serviço do Azure.
Ao decidir entre o modelo de webhook e a integração do Barramento de Serviço do Azure, tenha estes pontos em mente:
- Azure Service Bus é adequado para processamento em alta escala e fornece um mecanismo completo de enfileiramento caso o Dataverse esteja enviando muitos eventos por push.
- Os webhooks podem ser redimensionados apenas no ponto em que o serviço Web hospedado pode processar as mensagens.
- Os webhooks habilitam etapas síncronas e assíncronas. O Barramento de Serviço do Azure permite somente etapas assíncronas.
- Os webhooks enviam solicitações POST com conteúdo JSON e podem ser usados por qualquer linguagem de programação ou aplicativo Web hospedado em qualquer lugar.
- Os webhooks e o Barramento de Serviço do Azure podem ser invocados de um plug-in ou de uma atividade de fluxo de trabalho personalizada.
Introdução
O uso de webhooks envolve três partes:
- Criar ou configurar um serviço para consumir solicitações de webhook.
- Registrando a etapa do webhook no serviço Dataverse.
- Invocar um webhook usando um plug-in ou uma atividade de fluxo de trabalho personalizada.
Inicie registrando um WebHook de teste
Para entender como criar e configurar um serviço para consumir uma solicitação de WebHook do Dataverse, comece aprendendo a registrar um WebHook. Para obter mais informações, consulte Registrar um WebHook.
Depois de registrar um WebHook de exemplo, use um site de registro de solicitação para examinar os dados contextuais que são transmitidos. Para obter mais informações, consulte Testar o registro do WebHook com o site de registro de solicitação.
Dica
Concluir as etapas para registrar um WebHook de teste e examinar os dados contextuais que são passados torna o restante das informações neste tópico mais fácil de entender. Conclua estas etapas e retorne a este tópico.
Criar ou configurar um serviço para consumir solicitações do WebHook
Webhooks são simplesmente um padrão que você pode aplicar usando uma ampla gama de tecnologias. Não há estruturas, plataformas ou linguagens de programação necessárias que você deve usar. Use as habilidades e o conhecimento que tem para fornecer a solução apropriada.
O Azure Functions fornece uma excelente maneira de fornecer uma solução usando Webhooks, mas não é um requisito. Esta seção não fornece diretrizes para uma solução específica. Em vez disso, descreve os dados que o Dataverse passa para seu serviço que permitem que seu serviço adicione valor.
Conforme demonstrado no registro do WebHook de teste com o site de registro de solicitação, você pode registrar uma etapa de teste do WebHook e usar o site de registro de solicitação para capturar os tipos específicos de dados que seu aplicativo pode processar.
Dados passados para o serviço
A solicitação inclui três tipos de dados: cadeia de caracteres de consulta, dados de cabeçalho e corpo da solicitação.
Cadeia de consulta
Os únicos dados que você passa como uma cadeia de caracteres de consulta são os valores de autenticação se você configurar o WebHook para usar as opções WebhookKey ou HttpQueryString , conforme descrito nas opções de Autenticação.
Dados de cabeçalho
Se você escolher a opção de autenticação HttpHeader , use os pares chave/valor exigidos pelo serviço.
Você pode esperar que seu serviço receba os seguintes dados:
| Chave | Descrição do valor |
|---|---|
x-ms-dynamics-organization |
O nome de domínio do ambiente que envia a solicitação |
x-ms-dynamics-entity-name |
O nome lógico da tabela passada nos dados de contexto de execução. |
x-ms-dynamics-request-name |
O nome do evento para o qual a etapa do WebHook foi registrada. |
x-ms-correlation-request-id |
Identificador exclusivo para rastrear qualquer tipo de extensão. A plataforma usa essa propriedade para prevenção de loop infinito. Na maioria dos casos, você pode ignorar essa propriedade. Ao trabalhar com suporte técnico, esse valor pode ser usado para consultar a telemetria para entender o que ocorreu durante toda a operação. |
x-ms-dynamics-msg-size-exceeded |
Enviado somente quando o tamanho da carga HTTP excede 256 KB. |
Corpo da solicitação
O corpo contém uma cadeia de caracteres que representa o valor JSON de uma instância da RemoteExecutionContext classe. Esses são os mesmos dados enviados às integrações do Azure Service Bus.
O serviço criado deve analisar esses dados para extrair os itens relevantes de informações para que seu serviço forneça sua função. A maneira como você escolhe analisar esses dados depende da tecnologia que você está usando e de suas preferências.
O exemplo a seguir mostra os dados JSON serializados passados para uma etapa registrada com as seguintes propriedades:
| Propriedade | Descrição |
|---|---|
| Mensagem | Atualização |
| Entidade Principal | contato |
| Entidade Secundária | nenhum |
| Atributos de Filtragem | firstname,lastname |
| Executar no contexto do usuário | Usuário da Chamada |
| Ordem de Execução | 1 |
| Etapa de Execução do Pipeline de Eventos | Pós-Operação |
| Modo de Execução | Assíncrono |
{
"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"
}
Importante
Quando o tamanho de toda a carga HTTP excede 256 KB, o x-ms-dynamics-msg-size-exceeded cabeçalho é incluído e as seguintes RemoteExecutionContext propriedades são removidas:
Algumas operações não incluem essas propriedades.
Acionar um WebHook a partir de uma atividade de plug-in ou fluxo de trabalho
Como WebHook é uma espécie de endpoint de serviço, você pode invocá-lo usando um plug-in ou uma atividade de fluxo de trabalho, sem registrar uma etapa. Essa abordagem funciona da mesma maneira que para um ponto de extremidade do Barramento de Serviço do Azure. Você precisa fornecer o ServiceEndpointId à interface IServiceEndpointNotificationService. Para mais informações, consulte os exemplos a seguir do Barramento de Serviço do Azure:
- Exemplo: Plug-in personalizado com reconhecimento do Azure
- Exemplo: Atividade de fluxo de trabalho personalizada com reconhecimento do Azure
Solucionar problemas de registros do WebHook
Webhooks são relativamente simples. O serviço envia a solicitação e avalia a resposta. O sistema não consegue interpretar nenhum dado retornado com o corpo da resposta. Ele examina apenas o valor da resposta StatusCode .
O tempo limite é de 60 segundos. Geralmente, se nenhuma resposta for retornada antes do período de tempo limite ou se o valor da resposta StatusCode não estiver dentro do 2xx intervalo para indicar êxito, a operação falhará. A exceção é quando o erro retornado estiver na tabela a seguir:
| CódigoDeStatus | Descrição |
|---|---|
502 |
Gateway inválido |
503 |
Serviço indisponível |
504 |
Tempo de Espera do Gateway (Gateway Timeout) |
Esses erros indicam um problema de rede que pode ser resolvido com outra tentativa. O serviço WebHook faz mais uma tentativa somente quando esses códigos de erro são retornados.
Webhooks assíncronos
Se você registrar seu web hook para ser executado de forma assíncrona, poderá examinar a Tarefa do Sistema para obter detalhes sobre o erro. Para obter mais informações, consulte Trabalhos assíncronos com falha na consulta para uma determinada etapa.
Webhooks síncronos
Quando você optar por usar um modo de execução síncrono, qualquer falha será relatada novamente ao usuário do aplicativo com uma caixa de diálogo de erro Ponto de extremidade indisponível informando ao usuário que o ponto de extremidade de serviço do webhook pode estar configurado incorretamente ou não está disponível. A caixa de diálogo permitirá que você baixe um arquivo de log para obter detalhes sobre quaisquer erros.
Observação
Quando você registra um webhook para uma etapa síncrona, ele imediatamente envia os dados do contexto de execução para o endpoint configurado. Se ocorrer um erro após o envio da solicitação, a operação de dados será revertida, mas a solicitação enviada ao ponto de extremidade configurado não poderá ser retirada.
Próximas Etapas
Registrar um WebHook
Testar o registro do WebHook com o site de registro de requisições
Consulte também
Escrever um plug-in
Registrar um plug-in
Serviço assíncrono no Dataverse
Exemplo: Plug-in personalizado com reconhecimento do Azure
Exemplo: Atividade de fluxo de trabalho personalizada com reconhecimento do Azure
Azure Functions
Tabela ServiceEndpoint
Tabela SdkMessageProcessingStep
Tabela Assíncrona de Operations
RemoteExecutionContext
IServiceEndpointNotificationService