user6269864
user6269864

Reputation:

Differentiate whether IDialog was called using context.Call() or context.Forward() in Microsoft Bot Framework

I have a subdialog in a bot built using MS bot framework that starts as follows - the standard way:

    public async Task StartAsync(IDialogContext context)
    {
        var msg = "Let's find your flights! Tell me the flight number, city or airline.";
        var reply = context.MakeMessage();
        reply.Text = msg;
        //add quick replies here
        await context.PostAsync(reply);
        context.Wait(UserInputReceived);
    }

This dialog is called using two different ways, depending on whether in the previous screen the user tapped a button that says "Flights" or immediately entered a flight number. Here is the code from the parent dialog:

else if (response.Text == MainOptions[2]) //user tapped a button
{
    context.Call(new FlightsDialog(), ChildDialogComplete);
}
else //user entered some text instead of tapping a button
{
    await context.Forward(new FlightsDialog(), ChildDialogComplete,
                          activity, CancellationToken.None);
}

Question: how can I know (from within the FlightsDialog) whether that dialog was called using context.Call() or context.Forward()? This is because in the case of context.Forward(), StartAsync() shouldn't output the prompt asking the user to enter the flight number - they already did this.

The best idea I have is to save a flag in the ConversationData or user data, as below, and access it from the IDialog, but I thought there could be a better way?

public static void SetUserDataProperty(Activity activity, string PropertyName, string ValueToSet)
{
    StateClient client = activity.GetStateClient();
    BotData userData = client.BotState.GetUserData(activity.ChannelId, activity.From.Id);
    userData.SetProperty<string>(PropertyName, ValueToSet);
    client.BotState.SetUserDataAsync(activity.ChannelId, activity.From.Id, userData);
}

Upvotes: 3

Views: 3594

Answers (1)

rposbo
rposbo

Reputation: 327

Unfortunately Forward actually calls Call (and then does some other stuff afterwards), so your Dialog wouldn't be able to differentiate.

void IDialogStack.Call<R>(IDialog<R> child, ResumeAfter<R> resume)
{
    var callRest = ToRest(child.StartAsync);
    if (resume != null)
    {
        var doneRest = ToRest(resume);
        this.wait = this.fiber.Call<DialogTask, object, R>(callRest, null, doneRest);
    }
    else
    {
        this.wait = this.fiber.Call<DialogTask, object>(callRest, null);
    }
}

async Task IDialogStack.Forward<R, T>(IDialog<R> child, ResumeAfter<R> resume, T item, CancellationToken token)
{
    IDialogStack stack = this;
    stack.Call(child, resume);
    await stack.PollAsync(token);
    IPostToBot postToBot = this;
    await postToBot.PostAsync(item, token);
}

From https://github.com/Microsoft/BotBuilder/blob/10893730134135dd4af4250277de8e1b980f81c9/CSharp/Library/Dialogs/DialogTask.cs#L196

Upvotes: 4

Related Questions