Partager via


Implémentation de référence pour exemples de webhooks SharePoint

L’implémentation de référence de SharePoint PnP (Patterns and Practices) montre comment vous pouvez utiliser les webhooks SharePoint dans votre application. Les webhooks sont implémentées à l’aide de différents composants de Microsoft Azure, tels que les tâches web Azure, le serveur SQL Azure et les files d’attente de stockage Azure, afin de gérer les notifications de tâches web asynchrones.

L’implémentation de référence ne fonctionne qu’avec les webhooks de liste SharePoint.

Vous pouvez également suivre ces étapes en regardant la vidéo sur la chaîne YouTube de la communauté de plateforme Microsoft 365 (PnP) :

S’applique à Office 365 multi-locataire (MT).

Microsoft Azure est utilisé pour héberger les différents composants nécessaires à l’implémentation des webhooks SharePoint.

Le code source et d’autres éléments relatifs à l’implémentation de référence sont disponibles en deux versions :

Déployer l’implémentation de référence

L’application vous explique comment gérer les webhooks spécifiquement pour une liste SharePoint. Elle contient également une implémentation de référence d’un point de terminaison du service webhook que vous pouvez réutiliser dans vos projets de webhooks.

implémentation de référence pour webhooks SharePoint

Guides de déploiement

Présentation des webhooks

Les webhooks avertissent votre application des modifications apportées dans SharePoint qu’elle doit surveiller. Votre application n’a ainsi plus à rechercher régulièrement d’éventuelles modifications. Avec les webhooks, votre application reçoit une notification (modèle push) chaque fois qu’une modification est effectuée. Elles ne sont pas propres à Microsoft. Il s’agit d’une norme web universelle également adoptée par d’autres fournisseurs (par exemple, WordPress, GitHub, MailChimp et autres).

Ajouter un webhook à votre liste SharePoint

L’implémentation de référence fonctionne avec une liste SharePoint. Pour ajouter un webhook à une liste SharePoint, votre application crée tout d’abord un abonnement de webhook en envoyant une demande POST /_api/web/lists('list-id')/subscriptions. La demande inclut les éléments suivants :

  • Une charge qui identifie la liste pour laquelle vous ajoutez le webhook.
  • L’emplacement de l’URL de votre service webhook pour envoyer les notifications.
  • La date d’expiration du webhook.

Une fois que vous avez demandé à SharePoint d’ajouter votre webhook, SharePoint vérifie si le point de terminaison de votre service webhook existe. Il envoie une chaîne de validation au point de terminaison du service. SharePoint attend que le point de terminaison de votre service renvoie la chaîne de validation dans les cinq secondes. Si cette procédure échoue, la création du webhook est annulée. Si vous avez déployé votre service, la procédure fonctionne et SharePoint renvoie un message HTTP 201 en réponse à la requête GET initialement envoyée par l’application. La charge utile dans la réponse contient l’ID du nouvel abonnement de webhook.

Ajout d’un webhook

Si vous jetez un œil à l’implémentation de référence, vous verrez que toutes les opérations de webhook sont regroupées dans la classe WebHookManager du projet SharePoint.WebHooks.Common. Pour ajouter un webhook, vous devez utiliser la méthode AddListWebHookAsync :

/// <summary>
/// This method adds a webhook to a SharePoint list. Note that you need your webhook endpoint being passed into this method to be up and running and reachable from the internet
/// </summary>
/// <param name="siteUrl">Url of the site holding the list</param>
/// <param name="listId">Id of the list</param>
/// <param name="webHookEndPoint">Url of the webhook service endpoint (the one that will be called during an event)</param>
/// <param name="accessToken">Access token to authenticate against SharePoint</param>
/// <param name="validityInMonths">Optional webhook validity in months, defaults to 3 months, max is 6 months</param>
/// <returns>subscription ID of the new webhook</returns>
public async Task<SubscriptionModel> AddListWebHookAsync(string siteUrl, string listId, string webHookEndPoint, string accessToken, int validityInMonths = 3)
{
    // webhook add code...
}

Lorsque vous appelez SharePoint, vous devez fournir les informations d’authentification. Dans ce cas, vous utilisez un en-tête d’authentification Bearer avec un jeton d’accès. Pour obtenir le jeton d’accès, interceptez le jeton via un gestionnaire d’événements ExecutingWebRequest :

ClientContext cc = null;

// Create SharePoint ClientContext object...

// Add ExecutingWebRequest event handler
cc.ExecutingWebRequest += Cc_ExecutingWebRequest;

// Capture the OAuth access token since we want to reuse that one in our REST requests
private void Cc_ExecutingWebRequest(object sender, WebRequestEventArgs e)
{
  this.accessToken = e.WebRequestExecutor.RequestHeaders.Get("Authorization").Replace("Bearer ", "");
}

SharePoint appelle votre service Webhook

Lorsque SharePoint détecte une modification dans une liste pour laquelle vous avez créé un abonnement de webhook, le point de terminaison de votre service est appelé par SharePoint. Lorsque vous examinez la charge utile issue de SharePoint, vous pouvez remarquer que les propriétés suivantes sont importantes :

Propriété Description
ID de l’abonnement de webhook. Si vous souhaitez mettre à jour l’abonnement de webhook (par exemple, pour repousser l’expiration du webhook) vous devez disposer de cet ID.
ID de la liste pour laquelle la modification a eu lieu.
URL relative du serveur du site contenant la ressource pour laquelle la modification est survenue.

Remarque

SharePoint envoie simplement une notification indiquant qu’une modification a eu lieu, mais celle-ci ne précise pas la nature de la modification. Étant donné que vous obtenez des informations sur le site web et la liste qui ont été modifiés, vous pouvez utiliser le même point de terminaison de service pour gérer les événements de webhook issus de plusieurs sites et listes.

Lorsque votre service est appelé, il est important que votre service réponde par un message HTTP 200 en moins de cinq secondes. La suite de cet article fournit plus d’informations sur le délai de réponse, mais retenez déjà que vous devez gérer les notifications de manière asynchrone. Pour ce faire, dans cette implémentation de référence, vous utiliserez des tâches web Azure et des files d’attente de stockage Azure.

SharePoint appelle votre point de terminaison de webhook

Récupération des modifications sur lesquelles votre service doit agir

À l’étape précédente, le point de terminaison de votre service a été appelé, mais SharePoint vous a uniquement fourni des informations sur l’endroit où la modification est survenue, et non sur la nature de cette modification. Pour mieux comprendre ce qui a changé, vous devez utiliser l’API GetChanges() SharePoint, comme montré dans l’image suivante.

Async GetChanges

Vous pouvez obtenir plus d’informations sur l’implémentation de GetChanges() dans la méthode ProcessNotification, dans la casse ChangeManager du projet SharePoint.WebHooks.Common.

Pour éviter de recevoir la même modification à plusieurs reprises, il est important d’indiquer à SharePoint le point à partir duquel vous souhaitez obtenir les modifications. Pour cela, vous devez transmettre un jeton de modification, ce qui implique également que le point de terminaison de votre service doit conserver le dernier jeton de modification (valeur changeToken) utilisé afin qu’il puisse être utilisé la prochaine fois que le point de terminaison du service est appelé.

Voici quelques éléments clés à noter concernant les modifications :

  • SharePoint n’appelle pas votre service en temps réel : quand une modification se produit dans une liste comportant un webhook, SharePoint met un appel webhook en file d’attente. Une fois par minute, cette file d’attente est lue et les points de terminaison de service appropriés sont appelés. Ce regroupement des demandes est important. Par exemple, si un téléchargement en bloc de 1 000 enregistrements a lieu en même temps, le traitement par lots empêche SharePoint d’appeler votre point de terminaison 1 000 fois. Ainsi, votre point de terminaison n’est appelé qu’une seule fois, même si, lorsque vous appelez la méthode GetChanges(), vous recevez 1 000 événements de modification à traiter.
  • Pour garantir une réponse immédiate quel que soit le nombre de modifications, il est important que la charge de travail du point de terminaison de votre service s’exécute de façon asynchrone. Dans l’implémentation de référence, nous avons exploité la puissance d’Azure : le service sérialise la charge utile entrante et la stocke dans une file d’attente de stockage Azure, tandis qu’une tâche web Azure s’exécute en continu et vérifie les messages en file d’attente. Lorsque des messages se trouvent dans la file d’attente, la tâche web les traite et exécute également votre logique de façon asynchrone.

Flux de bout en bout

Le diagramme suivant décrit le flux complet des webhooks.

Implémentation de référence pour les webhooks - Flux de bout en bout

  1. Votre application crée un abonnement de webhook. Ce faisant, elle obtient la valeur changeToken actuelle à partir de la liste pour laquelle elle a créé le webhook.
  2. Votre application conserve la valeur changeToken dans un emplacement de stockage permanent, tel que SQL Azure, dans le cas présent.
  3. Une modification survient dans SharePoint, et SharePoint appelle le point de terminaison de votre service.
  4. Le point de terminaison de votre service sérialise la demande de notification et la stocke dans la file d’espace de stockage.
  5. Votre tâche web voit le message dans la file d’attente et démarre votre logique de traitement des messages.
  6. Votre logique de traitement des messages récupère le dernier jeton de modification utilisé à partir du stockage permanent.
  7. Votre logique de traitement des messages utilise l’API GetChanges() pour déterminer ce qui a changé.
  8. Les modifications renvoyées sont traitées et votre application applique maintenant les actions définies en fonction des modifications.
  9. Pour terminer, l’application conserve le dernier jeton de modification récupéré afin de ne pas recevoir de modifications déjà traitées la prochaine fois.

Utiliser le renouvellement de webhook

Les abonnements de webhook expirent au bout de six mois par défaut, ou à la date spécifiée lors de leur création. Vous avez souvent besoin de pouvoir disposer du webhook pendant plus longtemps. Les modèles décrits dans les sections suivantes permettent d’augmenter la durée de vie d’un abonnement de webhook. Le premier est léger, tandis que le second est légèrement plus complexe et requiert l’hébergement d’une tâche web supplémentaire.

Modèle de base

Lorsque votre service reçoit une notification, il obtient également des informations sur la durée de l’abonnement. Si l’abonnement est sur le point d’expirer, dans votre logique de traitement des notifications, vous étendez simplement la durée de vie de l’abonnement. Ce modèle est mis en œuvre dans cette implémentation de référence et fonctionne bien dans la plupart des cas. Toutefois, si aucune modification n’est apportée pendant six mois à la liste pour laquelle vous avez créé un abonnement de webhook, ce dernier n’est jamais prolongé et est supprimé.

Modèle fiable mais plus complexe

Créez une tâche web qui, une fois par semaine, lit tous les ID d’abonnement à partir de l’espace de stockage permanent. À chaque fois, prolongez un par un les abonnements trouvés.

Remarque

Cette tâche web n’est pas comprise dans cette implémentation de référence.

Le véritable renouvellement d’un webhook pour une liste SharePoint peut s’effectuer à l’aide d’un appel REST PATCH /_api/web/lists('list-id')/subscriptions(‘subscriptionID’).

Dans l’implémentation de référence, la mise à jour des webhooks est effectuée dans la classe WebHookManager du projet SharePoint.WebHooks.Common.

La mise à jour d’un webhook s’effectue à l’aide de la méthode UpdateListWebHookAsync :

/// <summary>
/// Updates the expiration datetime (and notification URL) of an existing SharePoint list webhook
/// </summary>
/// <param name="siteUrl">Url of the site holding the list</param>
/// <param name="listId">Id of the list</param>
/// <param name="subscriptionId">Id of the webhook subscription that we need to update</param>
/// <param name="webHookEndPoint">Url of the webhook service endpoint (the one that will be called during an event)</param>
/// <param name="expirationDateTime">New webhook expiration date</param>
/// <param name="accessToken">Access token to authenticate against SharePoint</param>
/// <returns>true if successful, exception in case something went wrong</returns>
public async Task<bool> UpdateListWebHookAsync(string siteUrl, string listId, string subscriptionId, string webHookEndPoint, DateTime expirationDateTime, string accessToken)
{
  // webhook update code...
}

Débogage de webhooks

Étant donné que SharePoint émet un appel vers le point de terminaison de votre service de webhook, votre point de terminaison doit être accessible par SharePoint. Cela complique légèrement les tâches de développement et de débogage. Voici quelques stratégies que vous pouvez utiliser pour vous simplifier la vie :

  • Lors du développement initial, fournissez votre propre charge sérialisée à la logique de traitement du service. Cela vous permet de tester entièrement votre logique de traitement sans déployer le point de terminaison de service (et même sans configurer de webhook).
  • Si vous avez accès aux ressources Azure, vous pouvez déployer votre point de terminaison sur Azure à l’aide d’une version de débogage et configurer Azure App Service pour le débogage. Cela vous permet de définir un point d’arrêt à distance et d’effectuer des tâches de débogage à distance à l’aide de Visual Studio.
  • Si vous ne souhaitez pas déployer votre service au moment du développement, vous devez utiliser un tunnel sécurisé pour votre service. L’idée est d’indiquer à SharePoint que le service de notification se trouve sur un point de terminaison public partagé. Dans le client, installez un composant qui se connecte à ce service public partagé ; chaque fois qu’un appel au point de terminaison public est effectué, le composant du client est averti et transmet la charge vers votre service exécuté sur l’hôte local. ngrok est une implémentation d’un outil de tunnel sécurisé de ce type que vous pouvez utiliser pour déboguer votre service Webhook localement.

Voir aussi