Kris
Kris

Reputation: 131

How to pass data from context.Forward and how to get the item in child dialog

I have one main dialog: MainDialog() and I want to send a message to child dialog: ChildDialog() using context.Forward().

I want to access the message I sent from MainDialog in StartAsync method of ChildDialog. The StartAsync method of ChildDialog has Context.Wait(MessageReceivedAsync). Based on the message I got from MainDialog (I want to send YES or NO string to childDialog), I want to take action.

If it is YES, I don't want to wait in ChildDialog and directly pass the message to MessageReceivedAsync handler.

How can I do this? I've looked at After call context.Forward, how to get the item in child dialog, but it is related to LuisDialog.

Upvotes: 0

Views: 283

Answers (1)

Kyle Delaney
Kyle Delaney

Reputation: 12284

While you can't pass data to StartAsync as an argument, there are a few ways you can pass data to your child dialog. Since you have control over your dialog's constructor, you can pass data as an argument to the constructor like this:

context.Forward(new ChildDialog(data), MessageReceivedAsync, item, token);

If you store the data in a property or field of your ChildDialog class, you'll be able to access that data in StartAsync.

You may have noticed context.Forward's item parameter. That's another way you can pass data to your child dialog, but it won't be available until after StartAsync has run. That said, you might want to reevaluate the design of your program flow. You say:

If it is YES, I don't want to wait in ChildDialog and directly pass the message to MessageReceivedAsync handler.

If you have context.Wait(MessageReceivedAsync) in your StartAsync method then you already won't wait in ChildDialog. This may be confusing, but even though you're calling context.Wait the message will immediately be passed along to MessageReceivedAsync because context.Forward sends the message to the dialog immediately after it calls StartAsync.

I'm guessing you want your bot to wait until the user sends another message if you pass "NO" to your child dialog. I don't know what you're trying to do with your bot, but I would consider not even starting your child dialog until the next turn in that case. If you really want to start the dialog and immediately wait, you might consider having two different ResumeAfter delegates:

[Serializable]
public class ChildDialog : IDialog<object>
{
    private string _data;

    public ChildDialog(string data)
    {
        _data = data
    }

    public Task StartAsync(IDialogContext context)
    {
        if (_data.Equals("YES"))
        {
            context.Wait(MessageReceivedAsync);
        }
        else
        {
            context.Wait(WaitAsync);
        }

        return Task.CompletedTask;
    }

    private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
    {
        // Respond to a message from the user
    }

    private async Task WaitAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
    {
        context.Wait(MessageReceivedAsync);
    }
}

Please have a look at the documentation for more information about dialogs: https://learn.microsoft.com/en-us/azure/bot-service/dotnet/bot-builder-dotnet-dialogs?view=azure-bot-service-3.0

Upvotes: 1

Related Questions