Sharat Gangadharan
Sharat Gangadharan

Reputation: 31

How to invoke a New Dialog from EventActivity Handler or any handler other than OnMessageActivityAsync?

I am trying to invoke a new Dialog on an event trigger in OnEventActivityAsync. I used DialogName (for eg EmployeeDetailsDialog Note: initialized in startup.cs. This is different from MainDialog which is instantiated with IBot implementation) and ran await EmployeeCardDialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);

This works but breaks after the first waterfall step and will not continue until it comes from OnMessageActivityAsync. Now since OnMessageActivityAsync code has await Dialog.Run(turnContext, ConversationState.CreateProperty<DialogState>("DialogState"), cancellationToken); it will go to MainDialog again(Dialog=MainDialog). I was assuming that dialogs will continue till they are finished so in this scenario EmployeeCardDialog should finish and then MainDialog should be triggered. Am I doing it wrong? ( I don't want to get rid of MainDialog. I want to invoke another dialog while OnMessageActivityAsync has MainDialog Triggering.) Thanks

DialogAndWelcomeBot.cs

protected override async Task OnEventActivityAsync(ITurnContext<IEventActivity> turnContext, CancellationToken cancellationToken)
        {switch (turnContext.Activity.Name)
            {
                case "EmployeeSearchButton":
                        await EmployeeCardDialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
}   
}               

DialogBot.cs

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            Logger.LogInformation("Running dialog with Message Activity.");

            await Dialog.Run(turnContext, ConversationState.CreateProperty<DialogState>("DialogState"), cancellationToken);

        }

EmployeeCardDialog.cs

    AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
            {
                        IntroStepAsync,
                        EmployeeSearchStepAsync,
                        FinalStepAsync

            }));

As you can see I want to run the EmployeeCardDialog when say that event is passed from directline (on a button click). Now if I run this this first step IntroStepAsync runs and prompts and exits the dialog. The next input obviously being a message has to be routed through DialogBots.cs OnMessageActivityAsync which handles messages to the bot. Like the code says it will go to MainDialog and then do something else entirely. I was expecting a behaviour where when I run EmployeeCardDialog, this runs till completion and then continue what I am doing. Am I doing this wrong or that is the intended behaviour?

Upvotes: 1

Views: 443

Answers (1)

JJeff
JJeff

Reputation: 121

I had a similar issue and I was able to resolve it by having a DialogSet singleton registered in startup and injecting this into my main bot class.

Inside the OnMessageAcitivtyAsync method I would call the CreateContextAsync method of the DialogSet to create a DialogContext. Once you have the DialogContext you can check if there is an active dialog if there is you can continue it, if not you can start a new dialog.

    protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
    {
        DialogContext dialogContext = await Dialogs.CreateContextAsync(turnContext, cancellationToken);

        if (dialogContext.ActiveDialog != null)
        {
            //Continue the current dialog
            await dialogContext.ContinueDialogAsync(cancellationToken);
            return;
        }

        await dialogContext.BeginDialogAsync(nameof(BaseDialog), null, cancellationToken);
    }

Regards,

Upvotes: 1

Related Questions