我在Bot Framework v4中从一个对话框移到另一个对话框时遇到了一些麻烦。我要完成的是从对话框X移到Y,然后从Y移回X。
例如,我有一个 GetShoppingCart 对话框,我想切换到 FindRecipe 对话框。我尝试添加 FindRecipe 对话框
(dc.Dialogs.Add(FindRecipeDialog.Id, recipe_dialog);
)到 GetShoppingCart的瀑布,但是一旦我在 FindRecipe 对话框中做同样的事情,就会出现无限循环。
这很麻烦,因为我需要添加此行才能访问对话框的目标ID。否则,当由Replace方法(await dc.Replace(FindRecipeDialog.Id, dialogArgs);
)调用时,它将无法被确认。
然后,我尝试将对话框对象从根对话框传递到 FindRecipe 和 GetShoppingCart 对话框,并在 GetShoppingCart 对话框中执行以下操作:
IDialog recipe_dialog = dialogs.Find(FindRecipeDialog.Id);
dc.Dialogs.Add(FindRecipeDialog.Id, recipe_dialog);
await dc.Replace(FindRecipeDialog.Id, dialogArgs);
有了这个,我能够成功进入 FindRecipe 对话框,而无需创建无限循环。 在 FindRecipe 对话框中,它执行第一个浪费步骤:
async(dc, args, next) =>
{
UserStateObject newUserStateObject;
var userState = UserState<UserState>.Get(dc.Context);
UserStateObject userStateObject = JsonConvert.DeserializeObject<UserStateObject>(userState.UserStateObject);
if (args == null) {
await FindRecipe(dc);
} else {
newUserStateObject = args["userState"] as UserStateObject;
if(newUserStateObject.UserInputs.UserRecipeChoices == RecipeUserChoicesEnum.AddAnotherProductChoice)
await AddOtherProductChoice(dc, userStateObject);
}
}
但是,仅完成一种方法之后,即使 FindRecipe 对话框中仍然存在瀑布步骤,它也可以返回 GetShoppingCart 对话框。在接下来的回合中,当尝试执行“ context.Continue()”时,它将引发此异常;
{System.Exception: DialogSet.continue(): Can't continue dialog. A dialog with an id of 'FindRecipe' wasn't found. at Microsoft.Bot.Builder.Dialogs.DialogContext.Continue() at Microsoft.Bot.Builder.Dialogs.DialogContainer.DialogContinue(DialogContext dc) at Microsoft.Bot.Builder.Dialogs.DialogContext.Continue() at RecipeBot.RecipesBot.OnTurn(ITurnContext context) ... }
我是否需要将 FindRecipe 对话框添加到dc.Dialogs某个时候再次出现?
我已经在dc.continue()(抛出异常的地方)之前尝试过了,但是在这种情况下,它会抛出:
{System.Exception: DialogSet.add(): A dialog with an id of 'FindRecipe' already added. at Microsoft.Bot.Builder.Dialogs.DialogSet.Add(String dialogId, IDialog dialog) at RecipeBot.RecipesBot.OnTurn(ITurnContext context) ... }
答案 0 :(得分:2)
我能够解决此问题。
每次收到消息时我都在创建一个新的对话,这导致了问题:
dialogs = new DialogSet();
dialogs.Add(GetShoppingCartDialog.Id, new GetShoppingCartDialog());
dialogs.Add(FindRecipeDialog.Id, new FindRecipeDialog());
要解决此问题,我使用了一个单例:创建每个对话框的实例并将其保存为对话框的变量。
dialogs = new DialogSet();
dialogs.Add(GetShoppingCartDialog.Id, GetShoppingCartDialog.Instance);
dialogs.Add(FindRecipeDialog.Id, FindRecipeDialog.Instance);