Übung: Zurückgeben von Produktdaten von der durch Microsoft Entra geschützten API
In dieser Übung aktualisieren Sie die Nachrichtenerweiterung, um Daten aus einer benutzerdefinierten API abzurufen. Sie erhalten Daten aus der benutzerdefinierten API basierend auf der Benutzerabfrage und geben Daten in Suchergebnissen an den Benutzer zurück.
Installieren und Konfigurieren von Dev Proxy
In dieser Übung verwenden Sie den Dev Proxy, ein Befehlszeilentool, das APIs simulieren kann. Dies ist nützlich, wenn Sie Ihre App testen möchten, ohne eine echte API erstellen zu müssen.
Um diese Übung abzuschließen, müssen Sie die neueste Version von Dev Proxy installieren und die Dev Proxy-Voreinstellung für dieses Modul herunterladen.
Die Voreinstellung simuliert eine CRUD-API (Create, Read, Update, Delete) mit einem In-Memory-Datenspeicher, der von Microsoft Entra geschützt wird. Dies bedeutet, dass Sie Ihre App so testen können, als würde sie eine echte API aufrufen, die eine Authentifizierung erfordert.
Führen Sie den folgenden Befehl in Ihrem Terminal aus, um die Voreinstellung herunterzuladen:
devproxy preset get learn-copilot-me-plugin
Abrufen des Benutzerabfragewerts
Erstellen Sie eine Methode, die den Benutzerabfragewert anhand des Namens des Parameters abruft.
In Visual Studio und im Projekt ProductsPlugin:
Erstellen Sie im Ordner Hilfsprogramme eine neue Datei mit dem Namen MessageExtensionHelpers.cs
Fügen Sie in der Datei den folgenden Code hinzu:
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; }
Save your changes
Aktualisieren Sie als Nächstes die OnTeamsMessagingExtensionQueryAsync-Methode , um die neue Hilfsmethode zu verwenden.
Öffnen Sie im Ordner SucheSearchApp.cs
Ersetzen Sie in der OnTeamsMessagingExtensionQueryAsync-Methode den folgenden Code:
var text = query?.Parameters?[0]?.Value as string ?? string.Empty;
mit
var text = MessageExtensionHelpers.GetQueryParameterValueByName(query.Parameters, "ProductName");
Bewegen Sie den Cursor in die Textvariable, verwenden Sie
Ctrl + R
,Ctrl + R
und benennen Sie die Variable in name um.Save your changes
Die OnTeamsMessagingExtensionQueryAsync-Methode sollte jetzt wie folgt aussehen:
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()
}
]
}
};
}
Abrufen von Daten aus der benutzerdefinierten API
Um Daten aus der benutzerdefinierten API abzurufen, müssen Sie das Zugriffstoken im Autorisierungsheader der Anforderung senden und die Antwort in ein Modell deserialisieren, das die Produktdaten darstellt.
Erstellen Sie zunächst ein Modell, das die Produktdaten darstellt, die von der benutzerdefinierten API zurückgegeben werden.
In Visual Studio und im Projekt ProductsPlugin:
Erstellen eines Ordners mit dem Namen Models
Erstellen Sie im Ordner Models eine neue Datei mit dem Namen Product.cs
Fügen Sie in der Datei den folgenden Code hinzu:
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; } }
Save your changes
Erstellen Sie als Nächstes eine Dienstklasse, die die Produktdaten aus der benutzerdefinierten API abruft.
Erstellen Eines Ordners mit dem Namen Services
Erstellen Sie im Ordner Dienste eine neue Datei mit dem Namen ProductService.cs
Fügen Sie in der Datei den folgenden Code hinzu:
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); } }
Save your changes
Die ProductsService-Klasse enthält Methoden zum Abrufen von Produktdaten aus der benutzerdefinierten API. Der Klassenkonstruktor verwendet ein Zugriffstoken als Parameter und richtet eine HttpClient-Instanz mit dem Zugriffstoken im Autorisierungsheader ein.
Aktualisieren Sie als Nächstes die OnTeamsMessagingExtensionQueryAsync-Methode , um die ProductsService-Klasse zum Abrufen von Produktdaten aus der benutzerdefinierten API zu verwenden.
Öffnen Sie im Ordner SucheSearchApp.cs
Fügen Sie in der OnTeamsMessagingExtensionQueryAsync-Methode den folgenden Code nach der Deklaration der Namensvariablen hinzu, um Produktdaten aus der benutzerdefinierten API abzurufen:
var productService = new ProductsService(tokenResponse.Token); var products = await productService.GetProductsByNameAsync(name);
Save your changes
Erstellen von Suchergebnissen
Nachdem Sie nun über die Produktdaten verfügen, können Sie sie in die Suchergebnisse aufnehmen, die an den Benutzer zurückgegeben werden.
Zunächst aktualisieren wir die vorhandene Vorlage für adaptive Karten, um die Produktinformationen anzuzeigen.
Fortfahren in Visual Studio und im Projekt ProductsPlugin:
Benennen Sie im Ordner Ressourcencard.json in Product.json
Erstellen Sie im Ordner Ressourcen eine neue Datei mit dem Namen Product.data.json. Diese Datei enthält Beispieldaten, die Visual Studio verwendet, um eine Vorschau der Vorlage für adaptive Karten zu generieren.
Fügen Sie in der Datei den folgenden JSON-Code hinzu:
{ "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" }
Save your changes
Öffnen Sie im Ordner RessourcenProduct.json
Ersetzen Sie in der Datei den Inhalt durch den folgenden JSON-Code:
{ "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')}" } ] } ] }
Save your changes
Die Vorlage adaptive Karte verwendet Bindungsausdrücke, um die Produktinformationen anzuzeigen. Die Ausdrücke ${name}, ${category}, ${imageUrl}, ${callVolume} und ${releaseDate} werden durch die entsprechenden Werte aus den Produktdaten ersetzt. Die Vorlagenfunktionen formatNumber und formatDateTime werden verwendet, um die CallVolume - und releaseDate-Werte in eine Zahl bzw. ein Datum zu formatieren.
Nehmen Sie sich einen Moment Zeit, um die Vorschau von adaptiven Karten in Visual Studio zu erkunden. Die Vorschau zeigt, wie die Vorlage für adaptive Karten aussieht, wenn die Produktdaten an die Vorlage gebunden sind. Es verwendet die Beispieldaten aus der Product.data.json-Datei , um die Vorschau zu generieren.
Aktualisieren Sie als Nächstes die validDomains-Eigenschaft im App-Manifest, um die raw.githubusercontent.com Domäne einzuschließen, damit die Bilder in der Vorlage für adaptive Karten in Microsoft Teams angezeigt werden können.
Im Projekt TeamsApp:
Öffnen Sie im Ordner appPackagemanifest.json
Fügen Sie in der Datei die GitHub-Domäne der validDomains-Eigenschaft hinzu:
"validDomains": [ "token.botframework.com", "raw.githubusercontent.com", "${{BOT_DOMAIN}}" ],
Save your changes
Aktualisieren Sie als Nächstes die OnTeamsMessagingExtensionQueryAsync-Methode , um eine Liste von Anlagen zu erstellen, die die Produktinformationen enthalten.
Im Projekt ProductsPlugin:
Öffnen Sie im Ordner SucheSearchApp.cs
Aktualisieren Sie card.json auf Product.json, um die Änderung im Dateinamen widerzuspiegeln. Ersetzen Sie den folgenden Code:
var card = await File.ReadAllTextAsync(Path.Combine(".", "Resources", "card.json"), cancellationToken);
mit
var card = await File.ReadAllTextAsync(Path.Combine(".", "Resources", "Product.json"), cancellationToken);
Fügen Sie den folgenden Code nach der Vorlagenvariablendeklaration hinzu, um eine Liste von Anlagen zu erstellen:
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();
Aktualisieren Sie die return-Anweisung , um die Attachments-Variable einzuschließen :
return new MessagingExtensionResponse { ComposeExtension = new MessagingExtensionResult { Type = "result", AttachmentLayout = "list", Attachments = attachments } };
Änderungen speichern
Erstellen und Aktualisieren von Ressourcen
Wenn alles vorhanden ist, führen Sie den Prozess Vorbereiten von Teams-App-Abhängigkeiten aus, um neue Ressourcen zu erstellen und vorhandene ressourcen zu aktualisieren.
Fahren Sie in Visual Studio fort:
- Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt TeamsApp .
- Erweitern Sie das Menü Teams Toolkit, wählen Sie Teams-App-Abhängigkeiten vorbereiten
- Wählen Sie im Dialogfeld Microsoft 365-KontoWeiteraus.
- Wählen Sie im Dialogfeld Bereitstellen die Option Bereitstellenaus.
- Wählen Sie im Warndialogfeld Teams ToolkitBereitstellenaus.
- Wählen Sie im Dialogfeld Informationen zum Teams-Toolkit das Kreuzsymbol aus, um das Dialogfeld zu schließen.
Ausführen und Debuggen
Starten Sie mit den bereitgestellten Ressourcen eine Debugsitzung, um die Nachrichtenerweiterung zu testen.
Starten Sie zunächst den Dev-Proxy, um die benutzerdefinierte API zu simulieren.
Öffnen eines Terminalfensters
Führen Sie den folgenden Befehl aus, um den Dev Proxy zu starten:
devproxy --config-file "~appFolder/presets/learn-copilot-me-plugin/products-api-config.json"
Wenn Sie dazu aufgefordert werden, akzeptieren Sie die Zertifikatwarnung.
Hinweis
Wenn Dev Proxy ausgeführt wird, fungiert er als systemweiter Proxy.
Starten Sie als Nächstes eine Debugsitzung in Visual Studio:
Um eine neue Debugsitzung zu starten, drücken Sie F5 , oder wählen Sie auf der Symbolleiste Start aus.
Warten Sie, bis ein Browserfenster geöffnet wird und das Dialogfeld für die App-Installation im Microsoft Teams-Webclient angezeigt wird. Wenn Sie dazu aufgefordert werden, geben Sie die Anmeldeinformationen Ihres Microsoft 365-Kontos ein.
Wählen Sie im Dialogfeld „App-Installation“ Hinzufügen aus
Öffnen Sie einen neuen oder vorhandenen Microsoft Teams-Chat
Wählen Sie im Nachrichtenerstellungsbereich aus + , um die App-Auswahl zu öffnen.
Wählen Sie in der Liste der Apps Contoso-Produkte aus, um die Nachrichtenerweiterung zu öffnen
Geben Sie in das Textfeld mark8 ein.
Warten Sie, bis die Suche abgeschlossen und die Ergebnisse angezeigt werden.
Wählen Sie in der Ergebnisliste ein Suchergebnis aus, um eine Karte in das Feld zum Verfassen von Nachrichten einzubetten.
Kehren Sie zu Visual Studio zurück, und wählen Sie auf der Symbolleiste Beenden aus, oder drücken Sie UMSCHALT + F5 , um die Debugsitzung zu beenden. Fahren Sie außerdem den Dev-Proxy mit STRG + C herunter.