Ejercicio: Devolución de datos de productos de Microsoft Entra API protegida
En este ejercicio, actualizará la extensión de mensaje para recuperar datos de una API personalizada. Obtiene datos de la API personalizada en función de la consulta del usuario y devuelve datos en los resultados de búsqueda al usuario.
Instalación y configuración del proxy de desarrollo
En este ejercicio, usará Dev Proxy, una herramienta de línea de comandos que puede simular las API. Resulta útil cuando se quiere probar la aplicación sin tener que crear una API real.
Para completar este ejercicio, debe instalar la versión más reciente de Dev Proxy y descargar el valor preestablecido Dev Proxy para este módulo.
El valor preestablecido simula una API CRUD (Crear, Leer, Actualizar, Eliminar) con un almacén de datos en memoria, que está protegido por Microsoft Entra. Esto significa que puede probar la aplicación como si llamara a una API real que requiere autenticación.
Para descargar el valor preestablecido, ejecute el siguiente comando en el terminal:
devproxy preset get learn-copilot-me-plugin
Obtención del valor de consulta de usuario
Cree un método que obtenga el valor de consulta de usuario por el nombre del parámetro.
En Visual Studio y el proyecto ProductsPlugin:
En la carpeta Helpers , cree un nuevo archivo denominado MessageExtensionHelpers.cs
En el archivo, agregue el código siguiente:
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
A continuación, actualice el método OnTeamsMessagingExtensionQueryAsync para usar el nuevo método auxiliar.
En la carpeta Buscar , abra SearchApp.cs
En el método OnTeamsMessagingExtensionQueryAsync , reemplace el código siguiente:
var text = query?.Parameters?[0]?.Value as string ?? string.Empty;
con
var text = MessageExtensionHelpers.GetQueryParameterValueByName(query.Parameters, "ProductName");
Mueva el cursor a la variable de texto, use
Ctrl + R
,Ctrl + R
y cambie el nombre de la variable por el nombre.Save your changes
El método OnTeamsMessagingExtensionQueryAsync ahora debería tener este aspecto:
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()
}
]
}
};
}
Obtención de datos de la API personalizada
Para obtener datos de la API personalizada, debe enviar el token de acceso en el encabezado Authorization de la solicitud y deserializar la respuesta en un modelo que represente los datos del producto.
En primer lugar, cree un modelo que represente los datos del producto devueltos desde la API personalizada.
En Visual Studio y el proyecto ProductsPlugin:
Crear una carpeta denominada Models
En la carpeta Modelos , cree un nuevo archivo denominado Product.cs
En el archivo, agregue el código siguiente:
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
A continuación, cree una clase de servicio que recupere los datos del producto de la API personalizada.
Creación de una carpeta denominada Servicios
En la carpeta Servicios , cree un nuevo archivo denominado ProductService.cs
En el archivo, agregue el código siguiente:
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
La clase ProductsService contiene métodos para obtener datos de producto de la API personalizada. El constructor de clase toma un token de acceso como parámetro y configura una instancia de HttpClient con el token de acceso en el encabezado Authorization.
A continuación, actualice el método OnTeamsMessagingExtensionQueryAsync para usar la clase ProductsService para obtener datos de producto de la API personalizada.
En la carpeta Buscar , abra SearchApp.cs
En el método OnTeamsMessagingExtensionQueryAsync , agregue el siguiente código después de la declaración de variable de nombre para obtener datos de producto de la API personalizada:
var productService = new ProductsService(tokenResponse.Token); var products = await productService.GetProductsByNameAsync(name);
Save your changes
Creación de resultados de búsqueda
Ahora que tiene los datos del producto, puede incluirlos en los resultados de búsqueda que se devuelven al usuario.
En primer lugar, vamos a actualizar la plantilla de tarjeta adaptable existente para mostrar la información del producto.
Continuando en Visual Studio y en el proyecto ProductsPlugin:
En la carpeta Recursos , cambie el nombre de card.json a Product.json
En la carpeta Recursos , cree un nuevo archivo denominado Product.data.json. Este archivo contiene datos de ejemplo que Visual Studio usa para generar una vista previa de la plantilla de tarjeta adaptable.
En el archivo , agregue el siguiente código JSON:
{ "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
En la carpeta Recursos , abra Product.json
En el archivo, reemplace el contenido por el siguiente JSON:
{ "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
La plantilla tarjeta adaptable usa expresiones de enlace para mostrar la información del producto. Las expresiones ${name}, ${category}, ${imageUrl}, ${callVolume}y ${releaseDate} se reemplazan por los valores correspondientes de los datos del producto. Las funciones de plantilla formatNumber y formatDateTime se usan para dar formato a los valores callVolume y releaseDate , en un número y una fecha respectivamente.
Tómese un momento para explorar la versión preliminar de la tarjeta adaptable en Visual Studio. En la vista previa se muestra cómo se ve la plantilla de tarjeta adaptable cuando los datos del producto están enlazados a la plantilla. Usa los datos de ejemplo del archivo Product.data.json para generar la vista previa.
A continuación, actualice la propiedad validDomains en el manifiesto de la aplicación para incluir el dominio raw.githubusercontent.com , de modo que las imágenes de la plantilla tarjeta adaptable se puedan mostrar en Microsoft Teams.
En el proyecto TeamsApp:
En la carpeta appPackage , abra manifest.json
En el archivo, agregue el dominio de GitHub a la propiedad validDomains :
"validDomains": [ "token.botframework.com", "raw.githubusercontent.com", "${{BOT_DOMAIN}}" ],
Save your changes
A continuación, actualice el método OnTeamsMessagingExtensionQueryAsync para crear una lista de datos adjuntos que contengan la información del producto.
En el proyecto ProductsPlugin:
En la carpeta Buscar , abra SearchApp.cs
Actualice card.json a Product.json para reflejar el cambio en el nombre de archivo. Reemplace el código siguiente:
var card = await File.ReadAllTextAsync(Path.Combine(".", "Resources", "card.json"), cancellationToken);
con
var card = await File.ReadAllTextAsync(Path.Combine(".", "Resources", "Product.json"), cancellationToken);
Agregue el código siguiente después de la declaración de variable de plantilla para crear una lista de datos adjuntos:
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();
Actualice la instrucción return para incluir la variable attachments :
return new MessagingExtensionResponse { ComposeExtension = new MessagingExtensionResult { Type = "result", AttachmentLayout = "list", Attachments = attachments } };
Guardar cambios
Creación y actualización de recursos
Con todo listo, ejecute el proceso Preparar dependencias de aplicaciones de Teams para crear nuevos recursos y actualizar los existentes.
Continuar en Visual Studio:
- En Explorador de soluciones, haga clic con el botón derecho en el proyecto TeamsApp
- Expanda el menú Kit de herramientas de Teams y seleccione Preparar dependencias de aplicaciones de Teams.
- En el cuadro de diálogo Cuenta de Microsoft 365, seleccione Continuar.
- En el cuadro de diálogo Aprovisionar , seleccione Aprovisionar.
- En el cuadro de diálogo de advertencia del kit de herramientas de Teams , seleccione Aprovisionar.
- En el cuadro de diálogo Información del kit de herramientas de Teams , seleccione el icono cruzado para cerrar el cuadro de diálogo.
Ejecución y depuración
Con los recursos aprovisionados, inicie una sesión de depuración para probar la extensión de mensaje.
En primer lugar, inicie Dev Proxy para simular la API personalizada.
Abrir una ventana de terminal
Ejecute el siguiente comando para iniciar dev Proxy:
devproxy --config-file "~appFolder/presets/learn-copilot-me-plugin/products-api-config.json"
Si se le solicita, acepte la advertencia del certificado.
Nota:
Cuando se ejecuta Dev Proxy, actúa como un proxy de todo el sistema.
A continuación, inicie una sesión de depuración en Visual Studio:
Para iniciar una nueva sesión de depuración, presione F5 o seleccione Iniciar en la barra de herramientas.
Espere hasta que se abra una ventana del explorador y aparezca el cuadro de diálogo de instalación de la aplicación en el cliente web de Microsoft Teams. Si se le solicita, escriba las credenciales de la cuenta de Microsoft 365.
En el cuadro de diálogo de instalación de la aplicación, seleccione Agregar.
Abrir un chat de Microsoft Teams nuevo o existente
En el área de redacción de mensajes, seleccione + para abrir el selector de aplicaciones.
En la lista de aplicaciones, seleccione Productos de Contoso para abrir la extensión de mensaje.
En el cuadro de texto, escriba mark8.
Espere a que se complete la búsqueda y se muestren los resultados.
En la lista de resultados, seleccione un resultado de búsqueda para insertar una tarjeta en el cuadro de mensaje de redacción.
Vuelva a Visual Studio y seleccione Detener en la barra de herramientas o presione Mayús + F5 para detener la sesión de depuración. Además, apague El proxy de desarrollo mediante Ctrl + C.