Partager via


Écrire un plug-in compatible Azure personnalisé

L’écriture d’un plug-in qui fonctionne avec Azure est similaire à l’écriture d’un autre plug-in Dataverse. Toutefois, en plus d’appeler toutes les méthodes de service web souhaitées, le plug-in doit inclure du code pour lancer la publication du contexte d’exécution de la transaction actuelle dans Azure Service Bus.

Considérations relatives à la conception des plug-ins

Pour un plug-in qui s’exécute de manière synchrone, la conception recommandée est destinée au plug-in pour envoyer un message à Azure pour récupérer des informations à partir d’une application d’écouteur ou d’un autre service externe. L’utilisation d’un contrat REST ou bidirectionnel sur le point de terminaison Azure Service Bus permet de retourner une chaîne de données au plug-in.

Il n’est pas recommandé qu’un plug-in synchrone utilise Azure Service Bus pour mettre à jour les données avec un service externe. Des problèmes peuvent survenir si le service externe devient indisponible ou s’il existe beaucoup de données à mettre à jour. Les plug-ins synchrones doivent s’exécuter rapidement et ne pas contenir tous les utilisateurs connectés d’une organisation pendant qu’une longue opération est effectuée. En outre, si une restauration de l’opération principale en cours qui a appelé le plug-in est effectuée, toutes les modifications de données apportées par le plug-in sont annulées. Ce retrait peut laisser Dataverse et un service externe dans un état non synchronisé.

Il est possible que les plug-ins inscrits synchrones publient le contexte d’exécution de la transaction actuelle dans Azure Service Bus.

Écrire le code du plug-in

Dans l’exemple de plug-in suivant, le code a été ajouté pour obtenir le fournisseur de services Azure et lancer la publication du contexte d’exécution dans Service Bus en appelant Execute(EntityReference, IExecutionContext). Du code de traçage a été ajouté pour faciliter le débogage du plug-in, car celui-ci doit s'exécuter dans un bac à sable virtuel.

Note

Le serviceEndpointId passé dans le constructeur de ce code est celui que vous obtenez en créant un point de terminaison de service, comme décrit dans Procédure pas à pas : Configurer Azure (SAS) pour l’intégration à Dataverse

Vous pouvez interroger des points de terminaison de service disponibles pour votre environnement à l’aide d’une requête adressée à l’API GET web à l’aide de votre navigateur avec une requête comme celle-ci : [organization Uri]/api/data/v9.0/serviceendpoints?$select=name,description,serviceendpointid

using System;
using System.Diagnostics;
using System.Threading;
using System.Runtime.Serialization;

using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;

using Microsoft.Xrm.Sdk;

namespace Microsoft.Crm.Sdk.Samples
{
    /// <summary>
    /// A custom plug-in that can post the execution context of the current message to the Windows
    /// Azure Service Bus. The plug-in also demonstrates tracing which assist with
    /// debugging for plug-ins that are registered in the sandbox.
    /// </summary>
    /// <remarks>This sample requires that a service endpoint be created first, and its ID passed
    /// to the plug-in constructor through the unsecure configuration parameter when the plug-in
    /// step is registered.</remarks>
    public sealed class SandboxPlugin : IPlugin
    {
        private Guid serviceEndpointId; 

        /// <summary>
        /// Constructor.
        /// </summary>
        public SandboxPlugin(string config)
        {
            if (String.IsNullOrEmpty(config) || !Guid.TryParse(config, out serviceEndpointId))
            {
                throw new InvalidPluginExecutionException("Service endpoint ID should be passed as config.");
            }
        }

        public void Execute(IServiceProvider serviceProvider)
        {
            // Retrieve the execution context.
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

            // Extract the tracing service.
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            if (tracingService == null)
                throw new InvalidPluginExecutionException("Failed to retrieve the tracing service.");

            IServiceEndpointNotificationService cloudService = (IServiceEndpointNotificationService)serviceProvider.GetService(typeof(IServiceEndpointNotificationService));
            if (cloudService == null)
                throw new InvalidPluginExecutionException("Failed to retrieve the service bus service.");

            try
            {
                tracingService.Trace("Posting the execution context.");
                string response = cloudService.Execute(new EntityReference("serviceendpoint", serviceEndpointId), context);
                if (!String.IsNullOrEmpty(response))
                {
                    tracingService.Trace("Response = {0}", response);
                }
                tracingService.Trace("Done.");
            }
            catch (Exception e)
            {
                tracingService.Trace("Exception: {0}", e.ToString());
                throw;
            }
        }
    }
}

Dans votre code de plug-in, vous pouvez mettre à jour les données accessibles en écriture dans le contexte avant de lancer le billet. Par exemple, vous pouvez ajouter une paire clé/valeur aux variables partagées dans le contexte.

Inscription des plug-ins

Il existe quelques restrictions lorsque vous inscrivez un plug-in personnalisé prenant en charge Azure. Le plug-in doit être inscrit pour s’exécuter dans le bac à sable. L'inscription au sandbox limite le plug-in à l’appel des méthodes IOrganizationService, aux méthodes de solution Azure ou à l’accès à un réseau à l’aide d’un client web. Aucun autre accès externe, tel que l’accès à un système de fichiers local, n’est autorisé.

Lorsqu'un plug-in est enregistré pour s'exécuter en mode asynchrone, l'ordre d'exécution de ce plug-in par rapport aux autres plug-ins asynchrones n'est pas garanti. En outre, les plug-ins asynchrones s’exécutent toujours après l’opération centrale de Dataverse.

Gérer un échec de publication du bus de services

Le comportement attendu d'un message Service Bus en échec dépend du fait que le plug-in a été inscrit pour exécution en mode synchrone ou asynchrone. Pour les plug-ins asynchrones, la tâche système qui publie en fin de compte le contexte d’exécution sur le bus de services réessaie la publication. Pour un plug-in synchrone enregistré, une exception est retournée. Plus d’informations sur la gestion et la notification des erreurs d’exécution

Important

Pour les plug-ins inscrits asynchrones uniquement, lorsque la tâche asynchrone qui publie sur Azure Service Bus est réessayée après un échec de publication, la logique de plug-in entière est exécutée à nouveau. En raison de cela, n’ajoutez aucune autre logique au plug-in personnalisé prenant en compte Azure autre que la modification du contexte et la publication dans Service Bus.

Pour qu’un plug-in inscrit s’exécute de manière asynchrone, le RemoteExecutionContext contenu contenu dans le corps du message envoyé sur Service Bus inclut une OperationId propriété et une OperationCreatedOn propriété. Ces propriétés contiennent les mêmes données que les AsyncOperationIdCreatedOn colonnes de l’enregistrement de travail système (AsyncOperation) associé. Ces propriétés supplémentaires facilitent le séquençage et la détection des doublons si le message Azure Service Bus doit être réessayé.

Voir aussi

Intégration d’Azure
Utiliser des données Microsoft Dataverse dans votre solution Azure
Exemple : Plug-in personnalisé compatible Azure
Écrire un plug-in
Pipeline d’exécution d’événements
Inscrire et déployer des plug-ins