当用户键入“退出”,“退出”等时,终止所有对话框并退出MS Bot Framework中的对话

我无法弄清楚如何在MS Bot Framework中做一个非常简单的事情:允许用户突破任何对话,离开当前对话框并通过键入“quit”,“exit”或“返回主菜单”重来”。

这是我的主要对话设置方式:

public async Task Post([FromBody]Activity activity) { try { if (activity.Type == ActivityTypes.Message) { UserActivityLogger.LogUserBehaviour(activity); if (activity.Text.ToLower() == "start over") { //Do something here, but I don't have the IDialogContext here! } BotUtils.SendTyping(activity); //send "typing" indicator upon each message received await Conversation.SendAsync(activity, () => new RootDialog()); } else { HandleSystemMessage(activity); } } 

我知道如何使用context.Done(this);终止对话框context.Done(this); ,但在这种方法中,我无法访问IDialogContext对象,因此我无法调用.Done()

当用户键入某个消息时,除了在所有对话框的每个步骤中添加一个检查之外,还有其他方法可以终止整个对话框堆栈吗?

发布赏金:

我需要一种终止所有IDialog的方法,而不使用我在这里发布的令人发指的黑客攻击(删除我需要的所有用户数据,例如用户设置和首选项)。

基本上,当用户键入“退出”或“退出”时,我需要退出当前正在进行的任何IDialog并返回到新状态,就好像用户刚刚发起了对话一样。

我需要能够从MessageController.cs,执行此操作MessageController.cs,我仍然无法访问IDialogContext 。 我似乎唯一有用的数据是Activity对象。 如果有人指出其他方法,我会很高兴。

另一种方法是找到一些其他方法来检查机器人的其他位置的“退出”和“退出”关键字,而不是在Post方法中。

但它不应该是在IDialog每一步都完成的检查,因为这是太多的代码甚至不可能(当使用PromptDialog ,我无法访问用户键入的文本)。

我没有探索的两种可能方式:

  • 而不是终止所有当前的IDialog ,与用户开始新的对话(new ConversationId
  • 获取IDialogStack对象并使用它来管理对话框堆栈。

Microsoft文档对此对象保持沉默,因此我不知道如何获取它。 我没有在机器人的任何地方使用允许.Switch()Chain对象,但是如果你认为它可以被重写以使用它,它也可以是解决这个问题的方法之一。 但是,我还没有找到如何在各种类型的对话框( FormFlow和普通的IDialog )之间进行分支,这些对话框又调用自己的子对话框等。

问题突然爆发

根据我对您的问题的理解,您想要实现的是重置对话框而不会完全破坏机器人状态


FACTS(从我从github存储库中读取的内容)

  1. 框架如何保存对话框堆栈如下:

BotDataStore> BotData> DialogStack

  1. BotFramework使用AutoFac作为DI容器
  2. DialogModule是用于对话框组件的Autofac模块

怎么做

从上面了解FACTS ,我的解决方案就是

  1. 注册依赖项,以便我们可以在我们的控制器中使用:

 // in Global.asax.cs var builder = new ContainerBuilder(); builder.RegisterModule(new DialogModule()); builder.RegisterModule(new ReflectionSurrogateModule()); builder.RegisterModule(new DialogModule_MakeRoot()); var config = GlobalConfiguration.Configuration; builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); builder.RegisterWebApiFilterProvider(config); var container = builder.Build(); config.DependencyResolver = new AutofacWebApiDependencyResolver(container); 
  1. 获取Autofac容器 (随意放在您熟悉的代码中的任何位置)

 private static ILifetimeScope Container { get { var config = GlobalConfiguration.Configuration; var resolver = (AutofacWebApiDependencyResolver)config.DependencyResolver; return resolver.Container; } } 
  1. 范围中加载BotData
  2. 加载DialogStack
  3. 重置DialogStack
  4. 将新BotData推回BotDataStore

 using (var scope = DialogModule.BeginLifetimeScope(Container, activity)) { var botData = scope.Resolve(); await botData.LoadAsync(default(CancellationToken)); var stack = scope.Resolve(); stack.Reset(); await botData.FlushAsync(default(CancellationToken)); } 

希望能帮助到你。


更新1(2016年8月27日)

感谢@ejadib指出, Container已经在会话类中公开了。

我们可以删除上面答案中的第2步,最后代码看起来像

 using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity)) { var botData = scope.Resolve(); await botData.LoadAsync(default(CancellationToken)); var stack = scope.Resolve(); stack.Reset(); await botData.FlushAsync(default(CancellationToken)); } 

这是一个非常难看的黑客行为。 它基本上删除了所有用户数据(您可能实际需要),这会导致对话重新启动。

如果有人知道更好的方式,而不删除用户数据,请分享。

  public async Task Post([FromBody]Activity activity) { try { if (activity.Type == ActivityTypes.Message) { //if the user types certain messages, quit all dialogs and start over string msg = activity.Text.ToLower().Trim(); if (msg == "start over" || msg == "exit" || msg == "quit" || msg == "done" || msg =="start again" || msg == "restart" || msg == "leave" || msg == "reset") { //This is where the conversation gets reset! activity.GetStateClient().BotState.DeleteStateForUser(activity.ChannelId, activity.From.Id); } //and even if we reset everything, show the welcome message again BotUtils.SendTyping(activity); //send "typing" indicator upon each message received await Conversation.SendAsync(activity, () => new RootDialog()); } else { HandleSystemMessage(activity); } } 

我知道这有点旧,但我遇到了同样的问题,而且发布的解决方案不再是最好的方法。

我不确定自哪个版本可用,但在3.8.1上您可以注册可在对话框中的任何位置触发的IScorable服务。

有一个示例代码显示它是如何工作的,它有一个“取消”全局命令处理程序:

https://github.com/Microsoft/BotBuilder-Samples/tree/master/CSharp/core-GlobalMessageHandlers

代码的一部分将如下所示:

 protected override async Task PostAsync(IActivity item, string state, CancellationToken token) { this.task.Reset(); } 

为其他人工作的其他代码:

 private async Task _reset(Activity activity) { await activity.GetStateClient().BotState .DeleteStateForUserWithHttpMessagesAsync(activity.ChannelId, activity.From.Id); var client = new ConnectorClient(new Uri(activity.ServiceUrl)); var clearMsg = activity.CreateReply(); clearMsg.Text = $"Reseting everything for conversation: {activity.Conversation.Id}"; await client.Conversations.SendToConversationAsync(clearMsg); } 

此代码由用户mmulhearn在此发布: https : //github.com/Microsoft/BotBuilder/issues/101#issuecomment-316170517