Botbuilder-dotnet: ReplaceDialogAsync doesn't change ActiveDialog

Created on 23 May 2019  路  6Comments  路  Source: microsoft/botbuilder-dotnet

Version

4.4.4

Describe the bug

After calling ReplaceDialogAsync, if we use an AdaptiveCard with a submit button, the OnEventAsync method should show, on our ActiveDialog property, the value of the new Dialog, but it shows the old Dialog.

For example, you have your MainDialog, which calls StartDialogAsync(nameof(FAQDialog)).
On your FAQDialog, you call ReplaceDialogAsync(nameof(AnotherDialog)).
If you use an AdaptiveCard with a Submit button on the "AnotherDialog", the event caught on the MainDialog (with the function "OnEventAsync") should show the ActiveDialog as "AnotherDialog", but shows as "FAQDialog".

To Reproduce

Steps to reproduce the behavior:

  1. Create a Virtual Assistant
  2. Use ReplaceDialogAsync on a Dialog A to Dialog B
  3. Insert an Adaptive Card with a Submit button on Dialog B
  4. Click the submit button
  5. Check the value of the ActiveDialog on the MainDialog

Expected behavior

Active Dialog should have the value of the dialog which replaced the old one.

[bug]

bug stale

Most helpful comment

@tiagodenoronha I hit this issue some time ago.

If I have understood this correctly (I have spent quite a bit of time looking into the code around this tonight), the ActiveDialog value is set when the inner dialog context state is re-hydrated when calling ContinueDialogAsync on the context, which only currently happens within the VA solution when continuing the current dialog (when a MessageActivity is received - https://github.com/microsoft/botframework-solutions/blob/c4ecbadc99d211f8f029c9da7d4899d5de4b287f/templates/Customer-Support-Template/CustomerSupportTemplate/Dialogs/Shared/RouterDialog.cs#L29). Because you are receiving an event, this gets handled within the MainDialog, which means your ActiveDialog will be showing as 'MainDialog' at this stage.

I am not totally clear at this point if this is actually bug, or simply a side effect of not continuing the current dialog, which the team may be able to clear up. However, until then I thought it might be useful to show you what I did to workaround this, which was by checking the state value of the ActiveDialog (MainDialog) instance for child dialogs on the stack. I realise it is not the nicest / cleanest solution, but hopefully it helps.


            if (dc.ActiveDialog != null)
            {
                var dialogId = dc.ActiveDialog.Id;
                var currentDialogState = dc.ActiveDialog.State.ContainsKey("dialogs") ? (DialogState)dc.ActiveDialog.State["dialogs"] : null;

                while (currentDialogState != null)
                {
                    if (currentDialogState.DialogStack != null && currentDialogState.DialogStack.Any() && currentDialogState.DialogStack.Count == 1)
                    {
                        dialogId = currentDialogState.DialogStack.First().Id;

                        currentDialogState = currentDialogState.DialogStack.First().State.ContainsKey("dialogs")
                            ? (DialogState)currentDialogState.DialogStack.First().State["dialogs"] : null;
                    }
                    else
                    {
                        currentDialogState = null;
                    }
                }
}

All 6 comments

@tiagodenoronha I hit this issue some time ago.

If I have understood this correctly (I have spent quite a bit of time looking into the code around this tonight), the ActiveDialog value is set when the inner dialog context state is re-hydrated when calling ContinueDialogAsync on the context, which only currently happens within the VA solution when continuing the current dialog (when a MessageActivity is received - https://github.com/microsoft/botframework-solutions/blob/c4ecbadc99d211f8f029c9da7d4899d5de4b287f/templates/Customer-Support-Template/CustomerSupportTemplate/Dialogs/Shared/RouterDialog.cs#L29). Because you are receiving an event, this gets handled within the MainDialog, which means your ActiveDialog will be showing as 'MainDialog' at this stage.

I am not totally clear at this point if this is actually bug, or simply a side effect of not continuing the current dialog, which the team may be able to clear up. However, until then I thought it might be useful to show you what I did to workaround this, which was by checking the state value of the ActiveDialog (MainDialog) instance for child dialogs on the stack. I realise it is not the nicest / cleanest solution, but hopefully it helps.


            if (dc.ActiveDialog != null)
            {
                var dialogId = dc.ActiveDialog.Id;
                var currentDialogState = dc.ActiveDialog.State.ContainsKey("dialogs") ? (DialogState)dc.ActiveDialog.State["dialogs"] : null;

                while (currentDialogState != null)
                {
                    if (currentDialogState.DialogStack != null && currentDialogState.DialogStack.Any() && currentDialogState.DialogStack.Count == 1)
                    {
                        dialogId = currentDialogState.DialogStack.First().Id;

                        currentDialogState = currentDialogState.DialogStack.First().State.ContainsKey("dialogs")
                            ? (DialogState)currentDialogState.DialogStack.First().State["dialogs"] : null;
                    }
                    else
                    {
                        currentDialogState = null;
                    }
                }
}

Hey Gary!
First of all thanks for the piece of code!
It doesn't always show up as MainDialog, if I use "BeginDialog", the ActiveDialog changes to the new Dialog.

Is was my understanding that using ReplaceDialog, it would EndDialog and then BeginDialog.
Does this not happen?

@tiagodenoronha Yes, that is what's happening under the hood (i.e. Ending the current Dialog and then Starting another), so I am not sure where the inconsistency is being introduced. I will do some further testing if I get a chance, but hopefully the code above will resolve your issue regardless of what the ActiveDialog is currently set to. I will let you know if I find anything else.

No worries! It isn't a blocking issue since, as you showed, there is a simple workaround for it!
I'll keep the issue open for further investigation anyone might find!

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days

Could it be that it's the Adaptive Cards that are returning to MainDialog? It might not be related to the ReplaceDialogAsync...

Was this page helpful?
0 / 5 - 0 ratings