Administración de una operación de ejecución prolongadaManage a long-running operation

se aplica a: SDK V4APPLIES TO: SDK v4

El control adecuado de las operaciones de ejecución larga es un aspecto importante de un bot sólido.Proper handling of long-running operations is an important aspect of a robust bot. Cuando el Azure Bot Service envía una actividad al bot desde un canal, se espera que el bot procese la actividad rápidamente.When the Azure Bot Service sends an activity to your bot from a channel, the bot is expected to process the activity quickly. Si el bot no completa la operación en un plazo de 10 a 15 segundos, en función del canal, el Azure Bot Service agotará el tiempo de espera y volverá a informar al cliente de un , como se describe en Funcionamiento de los 504:GatewayTimeout bots.If the bot does not complete the operation within 10 to 15 seconds, depending on the channel, the Azure Bot Service will timeout and report back to the client a 504:GatewayTimeout, as described in How bots work.

En este artículo se describe cómo usar un servicio externo para ejecutar la operación y notificar al bot cuando se haya completado.This article describes how to use an external service to execute the operation and to notify the bot when it has completed.

Requisitos previosPrerequisites

Acerca de este ejemploAbout this sample

Este artículo comienza con el bot de ejemplo de aviso de varios turnos y agrega código para realizar operaciones de ejecución larga.This article begins with the multi-turn prompt sample bot and adds code for performing a long-running operations. También muestra cómo responder a un usuario una vez completada la operación.It also demonstrates how to respond to a user after the operation has completed. En el ejemplo actualizado:In the updated sample:

  • El bot pregunta al usuario qué operación de ejecución larga se debe realizar.The bot asks the user which long-running operation to perform.
  • El bot recibe una actividad del usuario y determina qué operación realizar.The bot receives an activity from the user, and determines which operation to perform.
  • El bot notifica al usuario que la operación llevará algún tiempo y la envía a una función de C#.The bot notifies the user the operation will take some time and sends the operation off to a C# function.
    • El bot guarda el estado, lo que indica que hay una operación en curso.The bot saves state, indicating there is an operation in progress.
    • Mientras se ejecuta la operación, el bot responde a los mensajes del usuario y le notifica que la operación todavía está en curso.While the operation is running, the bot responds to messages from the user, notifying them the operation is still in progress.
    • Azure Functions administra la operación de ejecución larga y envía una actividad al bot y le notifica event que la operación se ha completado.Azure Functions manages the long-running operation and sends an event activity to the bot, notifying it that the operation completed.
  • El bot reanuda la conversación y envía un mensaje proactivo para notificar al usuario que se ha completado la operación.The bot resumes the conversation and sends a proactive message to notify the user that the operation completed. A continuación, el bot borra el estado de la operación mencionado anteriormente.The bot then clears the operation state mentioned earlier.

En este ejemplo se LongOperationPrompt define una clase derivada de la clase ActivityPrompt abstracta .This example defines a LongOperationPrompt class, derived from the abstract ActivityPrompt class. Cuando pone en cola la actividad que se va a procesar, incluye una opción del usuario dentro de la LongOperationPrompt propiedad value de la actividad.When the LongOperationPrompt queues the activity to be processed, it includes a choice from the user within the activity's value property. A continuación, esta actividad se consume Azure Functions, se modifica y encapsula en una actividad diferente antes de que se envíe de nuevo al bot mediante un event Direct Line cliente.This activity is then consumed by Azure Functions, modified, and wrapped in a different event activity before it is sent back to the bot using a Direct Line client. Dentro del bot, la actividad de evento se usa para reanudar la conversación mediante una llamada al método continue conversation del adaptador.Within the bot, the event activity is used to resume the conversation by calling the adapter's continue conversation method. A continuación, se carga la pila de diálogos y LongOperationPrompt se completa .The dialog stack is then loaded, and the LongOperationPrompt completes.

Este artículo trata sobre muchas tecnologías diferentes.This article touches on many different technologies. Consulte la sección de recursos adicionales para obtener vínculos a artículos asociados.See the additional resources section for links to associated articles.

Creación de una cuenta de Azure StorageCreate an Azure Storage account

Cree una Azure Storage de conexión y recupere la cadena de conexión.Create an Azure Storage account, and retrieve the connection string. Deberá agregar la cadena de conexión al archivo de configuración del bot.You will need to add the connection string to your bot's configuration file.

Para obtener más información, consulte Creación de una cuenta de almacenamiento y copia de las credenciales de Azure Portal.For more information, see create a storage account and copy your credentials from the Azure portal.

Creación de un Bot Channels RegistrationCreate a Bot Channels Registration

  1. Antes de crear el registro, configure ngrok y recupere una dirección URL que se usará como punto de conexión de mensajería del bot durante la depuración local.Before creating the registration, setup ngrok and retrieve a URL to be used as the bot's messaging endpoint during local debugging. El punto de conexión de mensajería será la dirección URL de reenvío HTTPS con /api/messages/ anexado.The messaging endpoint will be the HTTPS forwarding URL with /api/messages/ appended. Tenga en cuenta que el puerto predeterminado para los nuevos bots es 3978.Note that the default port for new bots is 3978.

    Para más información, consulte cómo depurar un bot mediante ngrok.For more information, see how to debug a bot using ngrok.

  2. Cree un registro de canales de bot en Azure Portal o con el CLI de Azure.Create a Bot Channels Registration in the Azure portal or with the Azure CLI. Establezca el punto de conexión de mensajería del bot en el que creó con ngrok.Set the bot's messaging endpoint to the one you created with ngrok. Una vez creado el recurso Registro de canales de bot, obtenga el identificador y la contraseña de la aplicación de Microsoft del bot.After the Bot Channels Registration resource is created, obtain the bot's Microsoft app ID and password. Habilite el canal Direct Line y recupere un Direct Line secreto.Enable the Direct Line channel, and retrieve a Direct Line secret. Los agregará al código del bot y a la función de C#.You will add these to your bot code and C# function.

    Para obtener más información, vea cómo administrar un bot y cómo conectar un bot a Direct Line.For more information, see how to manage a bot and how to connect a bot to Direct Line.

Creación de la función de C#Create the C# function

  1. Cree una Azure Functions basada en la .Net Core en tiempo de ejecución.Create an Azure Functions app based on the .Net Core runtime stack.

    Para obtener más información, vea cómo crear una aplicación de función y la referencia Azure Functions script de C#.For more information, see how to create a function app and the Azure Functions C# script reference.

  2. Agregue una DirectLineSecret configuración de aplicación a function app.Add a DirectLineSecret application setting to the Function App.

    Para obtener más información, vea cómo administrar la aplicación de función.For more information, see how to manage your function app.

  3. Dentro de function app, agregue una función basada en la plantilla Azure Queue Storage plantilla.Within the Function App, add a function based on the Azure Queue Storage template.

    Establezca el nombre de cola deseado y elija el Azure Storage Account que creó en un paso anterior.Set the desired queue name, and choose the Azure Storage Account created in an earlier step. Este nombre de cola también se colocará en el archivoappsettings.js del bot.This queue name will also be placed in the bot's appsettings.json file.

  4. Agregue un archivo function.proj a la función.Add a function.proj file to the function.

    <Project Sdk="Microsoft.NET.Sdk">
        <PropertyGroup>
            <TargetFramework>netstandard2.0</TargetFramework>
        </PropertyGroup>
    
        <ItemGroup>
            <PackageReference Include="Microsoft.Bot.Connector.DirectLine" Version="3.0.2" />
            <PackageReference Include="Microsoft.Rest.ClientRuntime" Version="2.3.4" />
        </ItemGroup>
    </Project>
    
  5. Actualice run.csx con el código siguiente:Update run.csx with the following code:

    #r "Newtonsoft.Json"
    
    using System;
    using System.Net.Http;
    using System.Text;
    using Newtonsoft.Json;
    using Microsoft.Bot.Connector.DirectLine;
    using System.Threading;
    
    public static async Task Run(string queueItem, ILogger log)
    {
        log.LogInformation($"C# Queue trigger function processing");
    
        JsonSerializerSettings jsonSettings = new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore };
        var originalActivity =  JsonConvert.DeserializeObject<Activity>(queueItem, jsonSettings);
        // Perform long operation here....
        System.Threading.Thread.Sleep(TimeSpan.FromSeconds(15));
    
        if(originalActivity.Value.ToString().Equals("option 1", CompareOptions.OrdinalIgnoreCase))
        {
            originalActivity.Value = " (Result for long operation one!)";
        }
        else if(originalActivity.Value.ToString().Equals("option 2", CompareOptions.OrdinalIgnoreCase))
        {
            originalActivity.Value = " (A different result for operation two!)";
        }
    
        originalActivity.Value = "LongOperationComplete:" + originalActivity.Value;
        var responseActivity =  new Activity("event");
        responseActivity.Value = originalActivity;
        responseActivity.Name = "LongOperationResponse";
        responseActivity.From = new ChannelAccount("GenerateReport", "AzureFunction");
    
        var directLineSecret = Environment.GetEnvironmentVariable("DirectLineSecret");
        using(DirectLineClient client = new DirectLineClient(directLineSecret))
        {
            var conversation = await client.Conversations.StartConversationAsync();
            await client.Conversations.PostActivityAsync(conversation.ConversationId, responseActivity);
        }
    
        log.LogInformation($"Done...");
    }
    

Creación del botCreate the bot

  1. Comience con una copia del ejemplo de símbolo del sistema de varios turnos de C#.Start with a copy of the C# Multi-Turn-Prompt sample.

  2. Agregue el paquete NuGet Azure.Storage.Queues al proyecto.Add the Azure.Storage.Queues NuGet package to your project.

  3. Agregue la cadena de conexión de la Azure Storage que creó anteriormente y el nombre de la cola de almacenamiento al archivo de configuración del bot.Add the connection string for the Azure Storage account you created earlier, and the Storage Queue Name, to your bot's configuration file.

    Asegúrese de que el nombre de la cola sea el mismo que el que usó para crear la función de desencadenador de cola anteriormente.Ensure the queue name is the same as the one you used to create the Queue Trigger Function earlier. Agregue también los valores de las propiedades MicrosoftAppId MicrosoftAppPassword y que generó anteriormente al crear el recurso Registro de canales de bot.Also add the values for the MicrosoftAppId and MicrosoftAppPassword properties that you generated earlier when you created the Bot Channels Registration resource.

    appsettings.jsonappsettings.json

    {
      "MicrosoftAppId": "<your-bot-app-id>",
      "MicrosoftAppPassword": "<your-bot-app-password>",
      "StorageQueueName": "<your-azure-storage-queue-name>",
      "QueueStorageConnection": "<your-storage-connection-string>"
    }
    
  4. Agregue un IConfiguration parámetro a DialogBot.cs para recuperar MicrsofotAppId .Add an IConfiguration parameter to DialogBot.cs in order to retrieve the MicrsofotAppId. Agregue también un OnEventActivityAsync controlador para desde la función de LongOperationResponse Azure.Also add an OnEventActivityAsync handler for the LongOperationResponse from the Azure Function.

    Bots\DialogBot.csBots\DialogBot.cs

    protected readonly IStatePropertyAccessor<DialogState> DialogState;
    protected readonly Dialog Dialog;
    protected readonly BotState ConversationState;
    protected readonly ILogger Logger;
    private readonly string _botId;
    
    /// <summary>
    /// Create an instance of <see cref="DialogBot{T}"/>.
    /// </summary>
    /// <param name="configuration"><see cref="IConfiguration"/> used to retrieve MicrosoftAppId
    /// which is used in ContinueConversationAsync.</param>
    /// <param name="conversationState"><see cref="ConversationState"/> used to store the DialogStack.</param>
    /// <param name="dialog">The RootDialog for this bot.</param>
    /// <param name="logger"><see cref="ILogger"/> to use.</param>
    public DialogBot(IConfiguration configuration, ConversationState conversationState, T dialog, ILogger<DialogBot<T>> logger)
    {
        _botId = configuration["MicrosoftAppId"] ?? Guid.NewGuid().ToString();
        ConversationState = conversationState;
        Dialog = dialog;
        Logger = logger;
        DialogState = ConversationState.CreateProperty<DialogState>(nameof(DialogState));
    }
    
    public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default)
    {
        await base.OnTurnAsync(turnContext, cancellationToken);
    
        // Save any state changes that might have occurred during the turn.
        await ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
    }
    
    protected override async Task OnEventActivityAsync(ITurnContext<IEventActivity> turnContext, CancellationToken cancellationToken)
    {
        // The event from the Azure Function will have a name of 'LongOperationResponse'
        if (turnContext.Activity.ChannelId == Channels.Directline && turnContext.Activity.Name == "LongOperationResponse")
        {
            // The response will have the original conversation reference activity in the .Value
            // This original activity was sent to the Azure Function via Azure.Storage.Queues in AzureQueuesService.cs.
            var continueConversationActivity = (turnContext.Activity.Value as JObject)?.ToObject<Activity>();
            await turnContext.Adapter.ContinueConversationAsync(_botId, continueConversationActivity.GetConversationReference(), async (context, cancellation) =>
            {
                Logger.LogInformation("Running dialog with Activity from LongOperationResponse.");
    
                // ContinueConversationAsync resets the .Value of the event being continued to Null, 
                //so change it back before running the dialog stack. (The .Value contains the response 
                //from the Azure Function)
                context.Activity.Value = continueConversationActivity.Value;
                await Dialog.RunAsync(context, DialogState, cancellationToken);
    
                // Save any state changes that might have occurred during the inner turn.
                await ConversationState.SaveChangesAsync(context, false, cancellationToken);
            }, cancellationToken);
        }
        else
        {
            await base.OnEventActivityAsync(turnContext, cancellationToken);
        }
    }
    
  5. Cree un servicio Azure Queues para poner en cola las actividades que deben procesarse.Create an Azure Queues service to queue activities which need to be processed.

    AzureQueuesService.csAzureQueuesService.cs

    /// <summary>
    /// Service used to queue messages to an Azure.Storage.Queues.
    /// </summary>
    public class AzureQueuesService
    {
        private static JsonSerializerSettings jsonSettings = new JsonSerializerSettings()
            {
                Formatting = Formatting.Indented,
                NullValueHandling = NullValueHandling.Ignore
            };
    
        private bool _createQueuIfNotExists = true;
        private readonly QueueClient _queueClient;
    
        /// <summary>
        /// Creates a new instance of <see cref="AzureQueuesService"/>.
        /// </summary>
        /// <param name="config"><see cref="IConfiguration"/> used to retrieve
        /// StorageQueueName and QueueStorageConnection from appsettings.json.</param>
        public AzureQueuesService(IConfiguration config)
        {
            var queueName = config["StorageQueueName"];
            var connectionString = config["QueueStorageConnection"];
    
            _queueClient = new QueueClient(connectionString, queueName);
        }
    
        /// <summary>
        /// Queue and Activity, with option in the Activity.Value to Azure.Storage.Queues
        ///
        /// <seealso cref="https://github.com/microsoft/botbuilder-dotnet/blob/master/libraries/Microsoft.Bot.Builder.Azure/Queues/ContinueConversationLater.cs"/>
        /// </summary>
        /// <param name="referenceActivity">Activity to queue after a call to GetContinuationActivity.</param>
        /// <param name="option">The option the user chose, which will be passed within the .Value of the activity queued.</param>
        /// <param name="cancellationToken">Cancellation token for the async operation.</param>
        /// <returns>Queued <see cref="Azure.Storage.Queues.Models.SendReceipt.MessageId"/>.</returns>
        public async Task<string> QueueActivityToProcess(Activity referenceActivity, string option, CancellationToken cancellationToken)
        {
            if (_createQueuIfNotExists)
            {
                _createQueuIfNotExists = false;
                await _queueClient.CreateIfNotExistsAsync().ConfigureAwait(false);
            }
    
            // create ContinuationActivity from the conversation reference.
            var activity = referenceActivity.GetConversationReference().GetContinuationActivity();
            // Pass the user's choice in the .Value
            activity.Value = option;
    
            var message = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(activity, jsonSettings)));
    
            // Aend ResumeConversation event, it will get posted back to us with a specific value, giving us 
            // the ability to process it and do the right thing.
            var reciept = await _queueClient.SendMessageAsync(message, cancellationToken).ConfigureAwait(false);
            return reciept.Value.MessageId;
        }
    }
    

Cuadros de diálogoDialogs

Quite el diálogo anterior y reemplázlo por nuevos diálogos para admitir las operaciones.Remove the old dialog and replace it with new dialogs to support the operations.

  1. Quite el archivo UserProfileDialog.cs.Remove the UserProfileDialog.cs file.

  2. Agregue un cuadro de diálogo de aviso personalizado que pregunte al usuario qué operación debe realizar.Add a custom prompt dialog that asks the user which operation to perform.

    Dialogs\LongOperationPrompt.csDialogs\LongOperationPrompt.cs

    /// <summary>
    /// <see cref="ActivityPrompt"/> implementation which will queue an activity,
    /// along with the <see cref="LongOperationPromptOptions.LongOperationOption"/>,
    /// and wait for an <see cref="ActivityTypes.Event"/> with name of "ContinueConversation"
    /// and Value containing the text: "LongOperationComplete".
    ///
    /// The result of this prompt will be the received Event Activity, which is sent by
    /// the Azure Function after it finishes the long operation.
    /// </summary>
    public class LongOperationPrompt : ActivityPrompt
    {
        private readonly AzureQueuesService _queueService;
    
        /// <summary>
        /// Create a new instance of <see cref="LongOperationPrompt"/>.
        /// </summary>
        /// <param name="dialogId">Id of this <see cref="LongOperationPrompt"/>.</param>
        /// <param name="validator">Validator to use for this prompt.</param>
        /// <param name="queueService"><see cref="AzureQueuesService"/> to use for Enqueuing the activity to process.</param>
        public LongOperationPrompt(string dialogId, PromptValidator<Activity> validator, AzureQueuesService queueService) 
            : base(dialogId, validator)
        {
            _queueService = queueService;
        }
    
        public async override Task<DialogTurnResult> BeginDialogAsync(DialogContext dc, object options, CancellationToken cancellationToken = default)
        {
            // When the dialog begins, queue the option chosen within the Activity queued.
            await _queueService.QueueActivityToProcess(dc.Context.Activity, (options as LongOperationPromptOptions).LongOperationOption, cancellationToken);
    
            return await base.BeginDialogAsync(dc, options, cancellationToken);
        }
    
        protected override Task<PromptRecognizerResult<Activity>> OnRecognizeAsync(ITurnContext turnContext, IDictionary<string, object> state, PromptOptions options, CancellationToken cancellationToken = default)
        {
            var result = new PromptRecognizerResult<Activity>() { Succeeded = false };
    
            if(turnContext.Activity.Type == ActivityTypes.Event
                && turnContext.Activity.Name == "ContinueConversation"
                && turnContext.Activity.Value != null
                // Custom validation within LongOperationPrompt.  
                // 'LongOperationComplete' is added to the Activity.Value in the Queue consumer (See: Azure Function)
                && turnContext.Activity.Value.ToString().Contains("LongOperationComplete", System.StringComparison.InvariantCultureIgnoreCase))
            {
                result.Succeeded = true;
                result.Value = turnContext.Activity;
            }
    
            return Task.FromResult(result);
        }
    }
    
  3. Agregue una clase de opciones de aviso para el símbolo del sistema personalizado.Add a prompt options class for the custom prompt.

    Dialogs\LongOperationPromptOptions.csDialogs\LongOperationPromptOptions.cs

    /// <summary>
    /// Options sent to <see cref="LongOperationPrompt"/> demonstrating how a value
    /// can be passed along with the queued activity.
    /// </summary>
    public class LongOperationPromptOptions : PromptOptions
    {
        /// <summary>
        /// This is a property sent through the Queue, and is used
        /// in the queue consumer (the Azure Function) to differentiate 
        /// between long operations chosen by the user.
        /// </summary>
        public string LongOperationOption { get; set; }
    }
    
  4. Agregue el cuadro de diálogo que usa el símbolo del sistema personalizado para obtener la elección del usuario e inicia la operación de ejecución larga.Add the dialog that uses the custom prompt to get the user's choice and initiates the long-running operation.

    Dialogs\LongOperationDialog.csDialogs\LongOperationDialog.cs

    /// <summary>
    /// This dialog demonstrates how to use the <see cref="LongOperationPrompt"/>.
    ///
    /// The user is provided an option to perform any of three long operations.
    /// Their choice is then sent to the <see cref="LongOperationPrompt"/>.
    /// When the prompt completes, the result is received as an Activity in the
    /// final Waterfall step.
    /// </summary>
    public class LongOperationDialog : ComponentDialog
    {
        public LongOperationDialog(AzureQueuesService queueService)
            : base(nameof(LongOperationDialog))
        {
            // This array defines how the Waterfall will execute.
            var waterfallSteps = new WaterfallStep[]
            {
                OperationTimeStepAsync,
                LongOperationStepAsync,
                OperationCompleteStepAsync,
            };
    
            // Add named dialogs to the DialogSet. These names are saved in the dialog state.
            AddDialog(new WaterfallDialog(nameof(WaterfallDialog), waterfallSteps));
            AddDialog(new LongOperationPrompt(nameof(LongOperationPrompt), (vContext, token) =>
            {
                return Task.FromResult(vContext.Recognized.Succeeded);
            }, queueService));
            AddDialog(new ChoicePrompt(nameof(ChoicePrompt)));
    
            // The initial child Dialog to run.
            InitialDialogId = nameof(WaterfallDialog);
        }
    
        private static async Task<DialogTurnResult> OperationTimeStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            // WaterfallStep always finishes with the end of the Waterfall or with another dialog; here it is a Prompt Dialog.
            // Running a prompt here means the next WaterfallStep will be run when the user's response is received.
            return await stepContext.PromptAsync(nameof(ChoicePrompt),
                new PromptOptions
                {
                    Prompt = MessageFactory.Text("Please select a long operation test option."),
                    Choices = ChoiceFactory.ToChoices(new List<string> { "option 1", "option 2", "option 3" }),
                }, cancellationToken);
        }
    
        private static async Task<DialogTurnResult> LongOperationStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            var value = ((FoundChoice)stepContext.Result).Value;
            stepContext.Values["longOperationOption"] = value;
    
            var prompt = MessageFactory.Text("...one moment please....");
            // The reprompt will be shown if the user messages the bot while the long operation is being performed.
            var retryPrompt = MessageFactory.Text($"Still performing the long operation: {value} ... (is the Azure Function executing from the queue?)");
            return await stepContext.PromptAsync(nameof(LongOperationPrompt),
                                                        new LongOperationPromptOptions
                                                        {
                                                            Prompt = prompt,
                                                            RetryPrompt = retryPrompt,
                                                            LongOperationOption = value,
                                                        }, cancellationToken);
        }
    
        private static async Task<DialogTurnResult> OperationCompleteStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            stepContext.Values["longOperationResult"] = stepContext.Result;
            await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Thanks for waiting. { (stepContext.Result as Activity).Value}"), cancellationToken);
    
            // Start over by replacing the dialog with itself.
            return await stepContext.ReplaceDialogAsync(nameof(WaterfallDialog), null, cancellationToken);
        }
    }
    

Registrar servicios y cuadro de diálogoRegister services and Dialog

En Startup.cs, actualice ConfigureServices el método para registrar y agregar LongOperationDialog AzureQueuesService .In Startup.cs, update the ConfigureServices method to register the LongOperationDialog and add the AzureQueuesService.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers().AddNewtonsoftJson();

    // Create the Bot Framework Adapter with error handling enabled.
    services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();

    // In production, this should be a persistent storage provider.bot
    services.AddSingleton<IStorage>(new MemoryStorage());

    // Create the Conversation state. (Used by the Dialog system itself.)
    services.AddSingleton<ConversationState>();

    // The Dialog that will be run by the bot.
    services.AddSingleton<LongOperationDialog>();

    // Service used to queue into Azure.Storage.Queues
    services.AddSingleton<AzureQueuesService>();

    // Create the bot as a transient. In this case the ASP Controller is expecting an IBot.
    services.AddTransient<IBot, DialogBot<LongOperationDialog>>();
}

Prueba del botTo test the bot

  1. Si aún no lo ha hecho, instale Bot Framework Emulator.If you have not done so already, install the Bot Framework Emulator.

  2. Ejecute el ejemplo localmente en la máquina.Run the sample locally on your machine.

  3. Inicie el emulador, conéctese al bot y envíe mensajes como se muestra a continuación.Start the Emulator, connect to your bot, and send messages as shown below.

    Ejemplo de bot

Recursos adicionalesAdditional resources

Herramienta o característicaTool or feature RecursosResources
Azure FunctionsAzure Functions Creación de una aplicación de funciónCreate a function app
Azure Functions script de C#Azure Functions C# script
Administración de la aplicación de funcionesManage your function app
Azure PortalAzure portal Administración de un botManage a bot
Conectar un bot con Direct LineConnect a bot to Direct Line
Azure StorageAzure Storage Azure Queue StorageAzure Queue Storage
Cree una cuenta de almacenamientoCreate a storage account
Copia de las credenciales desde Azure PortalCopy your credentials from the Azure portal
Uso de colasHow to Use Queues
Conceptos básicos de los botsBot basics Funcionamiento de los botsHow bots work
Avisos en diálogos en cascadaPrompts in waterfall dialogs
Mensajería proactivaProactive messaging
ngrokngrok Depuración de un bot mediante ngrokDebug a bot using ngrok