Devedse
Devedse

Reputation: 1861

When completing a subdialog in the Microsoft Bot framework V4, how do you continue on the parent dialog?

Introduction

Currently I'm trying to create a Bot Framework application using the Microsoft Bot Framework v4.

Structure of program

We currently have the following setup:

The root of the bot class is named: SubDialogBotBot

Within the SubDialogBot we create a new Dialog named ParentDialog. This Dialog is responsible for reacting to a specific Intent.

We then start a new Dialog from the ParentDialog named ChildDialog. This child dialog will be responsible for asking the user a question based on arguments passed by ParentDialog.

After this question completed we want to return to the ParentDialog and continue the flow.

In this example we want to re-use the ChildDialog from all kinds of different intents as the code in here is exactly the same. The only thing that changes is the questions that have to be asked to the user.

Problem

When the ChildDialog completes the 'flow' is never returned to the ParentDialog.

We also tried to have the Dialog following after the ChildDialog ID set to something specific and then call this using Context.BeginDialog(....) from the ChildDialog. However because apparently the dialog was added to the ParentDialog and not to the ChildDialog it can't find this by the id.

Github repository reproducing the problem

https://github.com/devedse/SubDialogBotReproduction

Upvotes: 4

Views: 852

Answers (1)

Drew Marsh
Drew Marsh

Reputation: 33379

First, this is an awesomely prepared question, thank you... especially for sharing the code.

Now, the good news is I don't think I see any problem with your dialogs. The problem is actually in your bot's OnTurnAsync. You are only ever calling BeginDialogAsync on your ParentDialog. Every single activity is going to come in through your OnTurnAsync and that means you're responsible for handling re-entrancy into the dialog stack. This means that, you need to check for an active dialog and, if there is one, you need to be calling ContinueDialogAsync instead to resume from where the discussion left off. Here's your current OnTurnAsync with the extra checks added:

public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
    // Create a dialog context
    var dc = await Dialogs.CreateContextAsync(turnContext);

    // Handle Message activity type, which is the main activity type for shown within a conversational interface

    // Message activities may contain text, speech, interactive cards, and binary or unknown attachments.

    // see https://aka.ms/about-bot-activity-message to learn more about the message and other activity types

    if (turnContext.Activity.Type == ActivityTypes.Message)
    {
        // If there's no active dialog, begin the parent dialog
        if(dc.ActivDialog == null)
        {
           await dc.BeginDialogAsync(nameof(ParentDialog));
        }
        else
        {
           await dc.ContinueDialogAsync();
        }


        // Save the new turn count into the conversation state.
        await _accessors.ConversationState.SaveChangesAsync(turnContext);
    }
    else
    {

        await turnContext.SendActivityAsync($"{turnContext.Activity.Type} event detected");
    }
}

Upvotes: 2

Related Questions