Exercice - Retourner des données de produit à partir de Microsoft Entra’API protégée

Effectué

Dans cet exercice, vous mettez à jour l’extension de message pour récupérer des données à partir d’une API personnalisée. Vous obtenez des données à partir de l’API personnalisée en fonction de la requête de l’utilisateur et retournez des données dans les résultats de recherche à l’utilisateur.

Capture d’écran des résultats de la recherche retournés par une extension de message basée sur la recherche dans Microsoft Teams.

Installer et configurer le proxy de développement

Dans cet exercice, vous utilisez dev Proxy, un outil en ligne de commande qui peut simuler des API. Il est utile lorsque vous souhaitez tester votre application sans avoir à créer une véritable API.

Pour effectuer cet exercice, vous devez installer la dernière version de Dev Proxy et télécharger la présélection dev Proxy pour ce module.

La présélection simule une API CRUD (Create, Read, Update, Delete) avec un magasin de données en mémoire, qui est protégé par Microsoft Entra. Cela signifie que vous pouvez tester votre application comme si elle appelait une API réelle qui nécessite une authentification.

Pour télécharger la présélection, exécutez la commande suivante dans votre terminal :

devproxy preset get learn-copilot-me-plugin

Obtenir la valeur de la requête utilisateur

Créez une méthode qui obtient la valeur de requête utilisateur par le nom du paramètre .

Dans Visual Studio et le projet ProductsPlugin :

  1. Dans le dossier Helpers , créez un fichier nommé MessageExtensionHelpers.cs

  2. Dans le fichier, ajoutez le code suivant :

    using Microsoft.Bot.Schema.Teams;
    
    internal class MessageExtensionHelpers
    {
        internal static string GetQueryParameterValueByName(IList<MessagingExtensionParameter> parameters, string name) => parameters.FirstOrDefault(p => p.Name == name)?.Value as string ?? string.Empty;
    }
    
  3. Save your changes

Ensuite, mettez à jour la méthode OnTeamsMessagingExtensionQueryAsync pour utiliser la nouvelle méthode d’assistance.

  1. Dans le dossier Rechercher , ouvrez SearchApp.cs

  2. Dans la méthode OnTeamsMessagingExtensionQueryAsync , remplacez le code suivant :

    var text = query?.Parameters?[0]?.Value as string ?? string.Empty;
    

    avec

    var text = MessageExtensionHelpers.GetQueryParameterValueByName(query.Parameters, "ProductName");
    
  3. Déplacez le curseur vers la variable de texte , utilisez Ctrl + R, Ctrl + Ret renommez la variable en nom

  4. Save your changes

La méthode OnTeamsMessagingExtensionQueryAsync doit maintenant ressembler à ceci :

protected override async Task<MessagingExtensionResponse> OnTeamsMessagingExtensionQueryAsync(ITurnContext<IInvokeActivity> turnContext, MessagingExtensionQuery query, CancellationToken cancellationToken)
{
    var userTokenClient = turnContext.TurnState.Get<UserTokenClient>();
    var tokenResponse = await AuthHelpers.GetToken(userTokenClient, query.State, turnContext.Activity.From.Id, turnContext.Activity.ChannelId, connectionName, cancellationToken);

    if (!AuthHelpers.HasToken(tokenResponse))
    {
        return await AuthHelpers.CreateAuthResponse(userTokenClient, connectionName, (Activity)turnContext.Activity, cancellationToken);
    }

    var name = MessageExtensionHelpers.GetQueryParameterValueByName(query.Parameters, "ProductName");

    var card = await File.ReadAllTextAsync(Path.Combine(".", "Resources", "card.json"), cancellationToken);
    var template = new AdaptiveCardTemplate(card);

    return new MessagingExtensionResponse
    {
        ComposeExtension = new MessagingExtensionResult
        {
            Type = "result",
            AttachmentLayout = "list",
            Attachments = [
                new MessagingExtensionAttachment
                    {
                        ContentType = AdaptiveCard.ContentType,
                        Content = JsonConvert.DeserializeObject(template.Expand(new { title = name })),
                        Preview = new ThumbnailCard { Title = name }.ToAttachment()
                    }
            ]
        }
    };
}

Obtenir des données à partir de l’API personnalisée

Pour obtenir des données à partir de l’API personnalisée, vous devez envoyer le jeton d’accès dans l’en-tête Authorization de la demande et désérialiser la réponse dans un modèle qui représente les données du produit.

Tout d’abord, créez un modèle qui représente les données de produit retournées par l’API personnalisée.

Dans Visual Studio et le projet ProductsPlugin :

  1. Créer un dossier nommé Models

  2. Dans le dossier Models , créez un fichier nommé Product.cs

  3. Dans le fichier, ajoutez le code suivant :

    using System.Text.Json.Serialization;
    
    internal class Product
    {
        [JsonPropertyName("productId")]
        public int Id { get; set; }
        [JsonPropertyName("imageUrl")]
        public string ImageUrl { get; set; }
        [JsonPropertyName("name")]
        public string Name { get; set; }
        [JsonPropertyName("category")]
        public string Category { get; set; }
        [JsonPropertyName("callVolume")]
        public int CallVolume { get; set; }
        [JsonPropertyName("releaseDate")]
        public string ReleaseDate { get; set; }
    }
    
  4. Save your changes

Ensuite, créez une classe de service qui récupère les données de produit à partir de l’API personnalisée.

  1. Créer un dossier nommé Services

  2. Dans le dossier Services , créez un fichier nommé ProductService.cs

  3. Dans le fichier, ajoutez le code suivant :

    using System.Net.Http.Headers;
    
    internal class ProductsService
    {
        private readonly HttpClient _httpClient;
        private readonly string _baseUri = "https://api.contoso.com/v1/";
    
        internal ProductsService(string token)
        {
            _httpClient = new HttpClient();
            _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
        }
    
        internal async Task<Product[]> GetProductsByNameAsync(string name)
        {
            var response = await _httpClient.GetAsync($"{_baseUri}products?name={name}");
            response.EnsureSuccessStatusCode();
            var jsonString = await response.Content.ReadAsStringAsync();
            return System.Text.Json.JsonSerializer.Deserialize<Product[]>(jsonString);
        }
    }
    
  4. Save your changes

La classe ProductsService contient des méthodes permettant d’obtenir des données de produit à partir de l’API personnalisée. Le constructeur de classe prend un jeton d’accès en tant que paramètre et configure un instance HttpClient avec le jeton d’accès dans l’en-tête Authorization.

Ensuite, mettez à jour la méthode OnTeamsMessagingExtensionQueryAsync pour utiliser la classe ProductsService pour obtenir des données de produit à partir de l’API personnalisée.

  1. Dans le dossier Rechercher , ouvrez SearchApp.cs

  2. Dans la méthode OnTeamsMessagingExtensionQueryAsync , ajoutez le code suivant après la déclaration de variable de nom pour obtenir les données de produit à partir de l’API personnalisée :

    var productService = new ProductsService(tokenResponse.Token);
    var products = await productService.GetProductsByNameAsync(name);
    
  3. Save your changes

Créer des résultats de recherche

Maintenant que vous disposez des données de produit, vous pouvez les inclure dans les résultats de recherche retournés à l’utilisateur.

Tout d’abord, nous allons mettre à jour le modèle de carte adaptative existant pour afficher les informations sur le produit.

Continuez dans Visual Studio et dans le projet ProductsPlugin :

  1. Dans le dossier Ressources, renommez carte.json en Product.json

  2. Dans le dossier Ressources , créez un fichier nommé Product.data.json. Ce fichier contient des exemples de données que Visual Studio utilise pour générer un aperçu du modèle de carte adaptative.

  3. Dans le fichier , ajoutez le code JSON suivant :

    {
      "callVolume": 36,
      "category": "Enterprise",
      "imageUrl": "https://raw.githubusercontent.com/SharePoint/sp-dev-provisioning-templates/master/tenant/productsupport/source/Product%20Imagery/Contoso4.png",
      "name": "Contoso Quad",
      "productId": 1,
      "releaseDate": "2019-02-09"
    }
    
  4. Save your changes

  5. Dans le dossier Ressources , ouvrez Product.json

  6. Dans le fichier, remplacez le contenu par le code JSON suivant :

    {
      "type": "AdaptiveCard",
      "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
      "version": "1.5",
      "body": [
        {
          "type": "TextBlock",
          "text": "${name}",
          "wrap": true,
          "style": "heading"
        },
        {
          "type": "TextBlock",
          "text": "${category}",
          "wrap": true
        },
        {
          "type": "Container",
          "items": [
            {
              "type": "Image",
              "url": "${imageUrl}",
              "altText": "${name}"
            }
          ],
          "minHeight": "350px",
          "verticalContentAlignment": "Center",
          "horizontalAlignment": "Center"
        },
        {
          "type": "FactSet",
          "facts": [
            {
              "title": "Call Volume",
              "value": "${formatNumber(callVolume,0)}"
            },
            {
              "title": "Release Date",
              "value": "${formatDateTime(releaseDate,'dd/MM/yyyy')}"
            }
          ]
        }
      ]
    }
    
  7. Save your changes

Le modèle de carte adaptative utilise des expressions de liaison pour afficher les informations sur le produit. Les expressions ${name}, ${category}, ${imageUrl}, ${callVolume} et ${releaseDate} sont remplacées par les valeurs correspondantes des données du produit. Les fonctions de modèle formatNumber et formatDateTime sont utilisées pour mettre en forme les valeurs callVolume et releaseDate , respectivement en nombre et date.

Prenez un moment pour explorer la préversion de la carte adaptative dans Visual Studio. L’aperçu montre à quoi ressemble le modèle de carte adaptative lorsque les données du produit sont liées au modèle. Il utilise les exemples de données du fichier Product.data.json pour générer l’aperçu.

Ensuite, mettez à jour la propriété validDomains dans le manifeste de l’application pour inclure le domaine raw.githubusercontent.com , afin que les images du modèle carte adaptative puissent être affichées dans Microsoft Teams.

Dans le projet TeamsApp :

  1. Dans le dossier appPackage , ouvrez manifest.json

  2. Dans le fichier, ajoutez le domaine GitHub à la propriété validDomains :

      "validDomains": [
        "token.botframework.com",
        "raw.githubusercontent.com",
        "${{BOT_DOMAIN}}"
      ],
    
  3. Save your changes

Ensuite, mettez à jour la méthode OnTeamsMessagingExtensionQueryAsync pour créer une liste de pièces jointes contenant les informations sur le produit.

Dans le projet ProductsPlugin :

  1. Dans le dossier Rechercher , ouvrez SearchApp.cs

  2. Mettez à jour carte.json sur Product.json pour refléter la modification du nom de fichier. Remplacez le code suivant :

    var card = await File.ReadAllTextAsync(Path.Combine(".", "Resources", "card.json"), cancellationToken);
    

    avec

    var card = await File.ReadAllTextAsync(Path.Combine(".", "Resources", "Product.json"), cancellationToken);
    
  3. Ajoutez le code suivant après la déclaration de variable de modèle pour créer une liste de pièces jointes :

     var attachments = products.Select(product =>
     {
         var content = template.Expand(product);
    
         return new MessagingExtensionAttachment
         {
             ContentType = AdaptiveCard.ContentType,
             Content = JsonConvert.DeserializeObject(content),
             Preview = new ThumbnailCard
             {
                 Title = product.Name,
                 Subtitle = product.Category,
                 Images = [new() { Url = product.ImageUrl }]
             }.ToAttachment()
         };
     }).ToList();
    
  4. Mettez à jour l’instruction return pour inclure la variable attachments :

    return new MessagingExtensionResponse
    {
        ComposeExtension = new MessagingExtensionResult
        {
            Type = "result",
            AttachmentLayout = "list",
            Attachments = attachments
        }
    };
    
  5. Enregistrer les modifications

Créer et mettre à jour des ressources

Une fois tout ce qui est maintenant en place, exécutez le processus Préparer les dépendances d’application Teams pour créer de nouvelles ressources et mettre à jour celles existantes.

Continuez dans Visual Studio :

  1. Dans Explorateur de solutions, cliquez avec le bouton droit sur le projet TeamsApp
  2. Développez le menu Kit de ressources Teams, sélectionnez Préparer les dépendances de l’application Teams.
  3. Dans la boîte de dialogue Compte Microsoft 365 , sélectionnez Continuer
  4. Dans la boîte de dialogue Provisionner , sélectionnez Provisionner
  5. Dans la boîte de dialogue d’avertissement du Kit de ressources Teams , sélectionnez Provisionner
  6. Dans la boîte de dialogue Informations du Kit de ressources Teams , sélectionnez l’icône en forme de croix pour fermer la boîte de dialogue

Exécuter et déboguer

Une fois les ressources approvisionnées, démarrez une session de débogage pour tester l’extension de message.

Tout d’abord, démarrez Dev Proxy pour simuler l’API personnalisée.

  1. Ouvrir une fenêtre de terminal

  2. Exécutez la commande suivante pour démarrer le proxy de développement :

    devproxy --config-file "~appFolder/presets/learn-copilot-me-plugin/products-api-config.json"
    
  3. Si vous y êtes invité, acceptez l’avertissement de certificat

Remarque

Lorsque le proxy de développement est en cours d’exécution, il agit comme un proxy à l’échelle du système.

Ensuite, démarrez une session de débogage dans Visual Studio :

  1. Pour démarrer une nouvelle session de débogage, appuyez sur F5 ou sélectionnez Démarrer dans la barre d’outils

  2. Attendez qu’une fenêtre de navigateur s’ouvre et que la boîte de dialogue d’installation de l’application s’affiche dans le client web Microsoft Teams. Si vous y êtes invité, entrez les informations d’identification de votre compte Microsoft 365.

  3. Dans la boîte de dialogue d’installation de l’application, sélectionnez Ajouter

  4. Ouvrir une conversation Microsoft Teams nouvelle ou existante

  5. Dans la zone de composition des messages, sélectionnez + pour ouvrir le sélecteur d’application

  6. Dans la liste des applications, sélectionnez Produits Contoso pour ouvrir l’extension de message

  7. Dans la zone de texte, entrez mark8

  8. Attendez que la recherche se termine et que les résultats s’affichent

    Capture d’écran des résultats de la recherche retournés par une extension de message basée sur la recherche dans Microsoft Teams.

  9. Dans la liste des résultats, sélectionnez un résultat de recherche pour incorporer un carte dans la zone de message de composition

Revenez à Visual Studio et sélectionnez Arrêter dans la barre d’outils, ou appuyez sur Maj + F5 pour arrêter la session de débogage. En outre, arrêtez le proxy de développement à l’aide de Ctrl + C.