Reputation: 1012
I need to do a condition depending on the Id of the active dialog something like this.
var dc = await _dialogs.CreateContextAsync(turnContext);
if (dc.ActiveDialog != null && dc.ActiveDialog.id == "SkipLuisDialog")
{
var interruptedQnaMaker = await IsTurnInterruptedDispatchToQnAMakerAsync(turnContext, topDispatch, QnaConfiguration, cancellationToken);
}
When i check my active dialog on OnTurnAsync()
like this:
if (dc.ActiveDialog != null)
{
await dc.Context.SendActivityAsync(dc.ActiveDialog.Id.ToString());
}
It always say "mainDialog" which is the ID of my main dialog. Even when im on the "FAQDialog" or "complaintDialog" the active dialog ID is always "mainDialog". Why is the active dialog Id not changing to "FAQDialog" when im in the FAQ dialog or to "complaintDialog" when im in the complaint dialog?
My main dialog and other dialogs are in another class.
This is how i call the mainDialog on OnTurnAsync()
:
if (!dc.Context.Responded)
{
switch (dialogResult.Status)
{
case DialogTurnStatus.Empty:
switch (topIntent) // topIntent // text
{
case GetStartedIntent:
await dc.BeginDialogAsync(MainDialogId);
break;
case NoneIntent:
default:
await dc.Context.SendActivityAsync("I didn't understand what you just said to me.");
break;
}
break;
case DialogTurnStatus.Waiting:
// The active dialog is waiting for a response from the user, so do nothing.
break;
case DialogTurnStatus.Complete:
await dc.EndDialogAsync();
break;
default:
await dc.CancelAllDialogsAsync();
break;
}
}
The Main Dialog:
namespace CoreBot.Dialogs
{ public class MainDialog : ComponentDialog { private const string InitialId = "mainDialog"; private const string TextPromptId = "textPrompt";
private const string ComplaintDialogId = "complaintDialog";
private const string FAQDialogId = "FAQDialog";
public MainDialog(string dialogId) : base(dialogId)
{
WaterfallStep[] waterfallSteps = new WaterfallStep[]
{
FirstStepAsync,
SecondStepAsync,
ThirdStepAsync,
};
AddDialog(new WaterfallDialog(InitialId, waterfallSteps));
AddDialog(new FAQDialog(FAQDialogId));
AddDialog(new FileComplaintDialog(ComplaintDialogId));
AddDialog(new TextPrompt(TextPromptId));
}
private static async Task<DialogTurnResult> FirstStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
{
return await stepContext.PromptAsync(
TextPromptId,
new PromptOptions
{
Prompt = new Activity
{
Type = ActivityTypes.Message,
Text = $"What can i do for you?",
SuggestedActions = new SuggestedActions()
{
Actions = new List<CardAction>()
{
new CardAction() { Title = "Frequently Asked Questions", Type = ActionTypes.ImBack, Value = "Frequently Asked Questions" },
new CardAction() { Title = "File a Complaint Ticket", Type = ActionTypes.ImBack, Value = "File a Complaint Ticket" },
},
},
},
});
}
private static async Task<DialogTurnResult> SecondStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
{
var response = stepContext.Result.ToString().ToLower();
string[] FAQArray = { "frequently asked questions", "question", "ask question" };
string[] ComplaintsArray = { "file a complaint ticket", "complaint", "file a complaint" };
if (FAQArray.Contains(response))
{
return await stepContext.BeginDialogAsync(FAQDialogId, cancellationToken);
}
if (ComplaintsArray.Contains(response))
{
await stepContext.EndDialogAsync();
return await stepContext.BeginDialogAsync(ComplaintDialogId, cancellationToken: cancellationToken);
}
return await stepContext.NextAsync();
}
private static async Task<DialogTurnResult> ThirdStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
{
return await stepContext.ReplaceDialogAsync(InitialId);
}
}
}
The Main Dialog calls 2 dialogs. This is one of them.
namespace CoreBot.Dialogs
{
public class FAQDialog : ComponentDialog
{
private const string InitialId = "FAQDialog";
private const string ChoicePromptId = "choicePrompt";
private const string TextPromptId = "textPrompt";
private const string ConfirmPromptId = "confirmPrompt";
public FAQDialog(string dialogId) : base(dialogId)
{
WaterfallStep[] waterfallSteps = new WaterfallStep[]
{
FirstStepAsync,
SecondStepAsync,
ThirdStepAsync,
FourthStepAsync,
};
AddDialog(new WaterfallDialog(InitialId, waterfallSteps));
AddDialog(new ChoicePrompt(ChoicePromptId));
AddDialog(new ConfirmPrompt(ConfirmPromptId));
AddDialog(new TextPrompt(TextPromptId));
}
private static async Task<DialogTurnResult> FirstStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
{
var choices = new List<Choice>();
choices.Add(new Choice { Value = "This is Sample Question 1", Synonyms = new List<string> { "Question 1" } });
choices.Add(new Choice { Value = "This is Sample Question 2", Synonyms = new List<string> { "Question 2" } });
return await stepContext.PromptAsync(
ChoicePromptId,
new PromptOptions
{
Prompt = MessageFactory.Text($"Welcome to FAQ! Choose the number of the question or type your own question."),
Choices = choices,
});
}
private static async Task<DialogTurnResult> SecondStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
{
var choiceResult = (stepContext.Result as FoundChoice).Value.ToLower();
switch (choiceResult)
{
case "this is sample question 1":
await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Answer to question 1."));
break;
case "this is sample question 2":
await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Answer to question 2."));
break;
default:
break;
}
return await stepContext.NextAsync();
}
private static async Task<DialogTurnResult> ThirdStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
{
return await stepContext.PromptAsync(
ConfirmPromptId,
new PromptOptions
{
Prompt = MessageFactory.Text($"Have another question?"),
});
}
private static async Task<DialogTurnResult> FourthStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
{
var confirmResult = (bool)stepContext.Result;
if (confirmResult)
{
await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Ask away!"));
return await stepContext.ReplaceDialogAsync(InitialId);
}
else
{
await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Great!"));
return await stepContext.EndDialogAsync();
}
}
}
}
Upvotes: 1
Views: 398
Reputation: 7241
This is because all of your dialogs are being called within MainDialog
.
Here's more or less what's going on:
In MyBot.cs
(or whatever your main .cs
file is), you have something like Dialogs = new DialogSet(_dialogStateAccessor)
which creates an empty dialog stack:
___________
You then use something like await dc.BeginDialogAsync(MainDialogId);
, which adds MainDialog
to the top of your dialog stack:
______________
| MainDialog |
|______________|
If you call return await stepContext.BeginDialogAsync(FAQDialogId, cancellationToken);
outside of your MainDialog, your stack will look something like this:
______________
| FAQDialogId |
|______________|
______________
| MainDialog |
|______________|
However, you call return await stepContext.BeginDialogAsync(FAQDialogId, cancellationToken);
from within MainDialog, which has it's own stack, so FAQDialog is the active dialog within MainDialog, but your Dialogs
stack still has MainDialog as the ActiveDialog. So, your stack is more or less like this:
_______________________
| ______________ |
| |__FAQDialog__| |
| |
| MainDialog |
|_______________________|
You have a couple of options:
1. Call all of your other dialogs from outside of MainDialog
.
If you're not going to come back to MainDialog
, you could do something like:
In MainDialog
:
return await stepContext.EndDialogAsync("FAQDialog");
In MyBot.cs
:
switch (dialogResult)
{
case "FAQDialog":
dc.BeginDialogAsync(FAQDialogId, cancellationToken);
break;
case "ComplaintDialog":
dc.BeginDialogAsync(ComplaintDialogId, cancellationToken);
break;
}
2. Dig for the the dialog's ID within the ActiveDialog's stack
if (dc.ActiveDialog != null && IsDialogInStack(dc.ActiveDialog, "SkipLuisDialog"))
{
var interruptedQnaMaker = await IsTurnInterruptedDispatchToQnAMakerAsync(turnContext, topDispatch, QnaConfiguration, cancellationToken);
}
[...]
private bool IsDialogInStack(DialogInstance activeDialog, string searchId)
{
if (activeDialog.Id == searchId)
{
return true;
};
foreach (KeyValuePair<string, object> item in activeDialog.State)
{
if (item.Key == "dialogs" && item.Value is DialogState)
{
DialogState dialogState = (DialogState)item.Value;
foreach (DialogInstance dialog in dialogState.DialogStack)
{
return IsDialogInStack(dialog, searchId);
}
}
}
return false;
}
Note: I'm not a C# expert and there might be a better way to code IsDialogInStack
, but the code above works fine.
Upvotes: 1