Search code examples
c#botframeworkchatbot

Bot framework v4 how to wait within a dialog for user to respond to a prompt


Within main prompt I would like to call child dialog that prompts user for input (ChoicePrompt), save that result to a variable and work with that result.

In sample code what actually ends up happening is that child dialog gets fired but code in main dialog continues before child dialog is finished (before user input).

Sample code of what I would like to achieve:

private async Task<DialogTurnResult> IntentCheckStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    LuisResult = await InDocRecognizer.RecognizeAsync<InDocChatbotService>(stepContext.Context, cancellationToken);
    var topIntent = LuisResult.TopIntent().intent;
    if (LuisResult.TopIntent().score < 0.30)
    {
        topIntent = InDocChatbotService.Intent.None;
    }
    // if first and second option is close in score prompt user choice between them
    else if (LuisResult.Intents.ElementAt(0).Value.Score - LuisResult.Intents.ElementAt(1).Value.Score < 0.20)
    {
        var topIntent = await stepContext.BeginDialogAsync(nameof(ChooseIntentDialog), LuisResult, cancellationToken);
        // Code in this dialog continues before user gives input to child dialog "ChooseIntentDialog"
    }

    // DO MORE STUFF WITH VARIABLE topIntent
}        

I do have a workaround but it's ugly and brakes code style. The way I do it is I return the child dialog and then handle things from ChooseIntentDialog in another waterfall step within main dialog.

This is bad because I need to carry multiple variables to that waterfall step and it just seems completely unnecessary. If I could just make waterfall step wait for child dialog and return it's result without having to do that with another waterfall step.

Is this possible? And if not what is the alternative as my solution does not seem to be very efficient code wise.


Solution

  • You cannot return to the middle of a step in waterfall dialogs. If you return await stepContext.BeginDialogAsync(nameof(ChooseIntentDialog)...) and then pass the chosen value back in return await stepContext.endDialogAsync(topIntent) if a choice needs to be made, or from main dialog just use return await stepContext.next(topIntent) if it does not, you will have access to the top intent in stepContext.result in your next step. You would just move // DO MORE STUFF WITH VARIABLE topIntent to your next step.