Piyush Khanna
Piyush Khanna

Reputation: 306

Bot Framework, Using C#, Hold conversation in child dialog

I have a parent dialog that throws a prompt to the user and gives some options to choose from. Based on the chosen option, I call the child dialog. Now, in the child dialog, I want to first give the instructions and ask the user to provide data based on instructions. So, after giving instructions, I want to wait for user's input. Using the below code, the execution goes back to parent dialog after giving the message about instructions and executes the child dialog post completion method on the parent (in my code below the function - "AfterAllDoneAsync"). Can someone help here?

Below is my code -

Message Controller

  public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
    {
        if (activity.Type == ActivityTypes.Message)
        {
            await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());
        }
        else
        {
            HandleSystemMessage(activity);
        }
        var response = Request.CreateResponse(HttpStatusCode.OK);
        return response;
    }

Root dialog

public Task StartAsync(IDialogContext context)
    {
        context.Wait(MessageReceivedAsync);

        return Task.CompletedTask;
    }

    private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
    {

        var activity = await result as Activity;
        string txt = activity.Text.ToLower() + " ";

        if (txt.StartsWith("Image"))
        {
            // Prompt user with options and based on chosen option, call child dialog
            var opt = new PromptOptions<String>("Choose from following -", "Didn't get that, please try again", "You are tough! I give up!", new string[] { "one", "two", "three" });
        PromptDialog.Choice(context, AfterPromptAsync, opt);

        }
    }

 public async Task AfterPromptAsync(IDialogContext context, IAwaitable<string> argument)
    {
        var confirm = await argument;
        if (confirm == "one")
        { 
            // call child dialog
            await context.Forward(new ChildDialog(), AfterAllDoneAsync, context.Activity,CancellationToken.None);
        }
        context.Wait(MessageReceivedAsync);
    }
    public async Task AfterAllDoneAsync(IDialogContext context, IAwaitable<object> argument)
    {
        await context.PostAsync("It was really great talking to you!");
        context.Wait(MessageReceivedAsync);
    }

Child Dialog

 public Task StartAsync(IDialogContext context)
    {
        context.Wait(this.MessageReceivedAsync);
        return Task.CompletedTask;
    }

    private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
    {
        var act = await result as Activity;
        if(act.Attachments.Count == 0)
        {
            await context.PostAsync("Follow these instrutions bla bla bla");
        }
        // Then i want to wait for the user to provide the needed data as per instructions but the control goes back to root dialog
        context.Wait(this.MessageReceivedAsync);
    }

Here is the output

U- Image

Bot - Choose from following - one two three

U - one

Bot - Follow these instrutions bla bla bla It was really great talking to you!

Upvotes: 0

Views: 607

Answers (1)

Ezequiel Jadib
Ezequiel Jadib

Reputation: 14787

You are forwarding to the child dialog and also waiting in the first dialog. You need to update the code of AfterPromptAsync to wait only if you don't forward (basically adding an else :)).

    public async Task AfterPromptAsync(IDialogContext context, IAwaitable<string> argument)
    {
        var confirm = await argument;
        if (confirm == "one")
        { 
            // call child dialog
            await context.Forward(new ChildDialog(), AfterAllDoneAsync, context.Activity,CancellationToken.None);
        }
        else 
        {
          context.Wait(MessageReceivedAsync);
        }
    }

Upvotes: 2

Related Questions