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

这是我建立主要对话的方式:

    public async Task<HttpResponseMessage> 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<DialogType>(this);终止对话框,但是在这种方法中,我无权访问IDialogContext对象,因此无法调用.Done()

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

发布赏金:

我需要一种方法来终止所有IDialog,而不使用我在此处发布的骇人听闻的技巧(该技巧会删除我需要的所有用户数据,例如用户设置和首选项)。

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

我需要能够从MessageController.cs,做到这一点,但仍然无法访问IDialogContext。我似乎只有的有用数据是Activity对象。如果有人指出其他方法可以使我感到高兴。

解决此问题的另一种方法是找到另一种方法来检查bot的其他位置(而不是在Post方法中)“退出”和“退出”关键字。

但这不应该在IDialog的每个步骤中进行的检查,因为这是太多的代码,甚至不总是可能的(使用PromptDialog时,我无法访问用户键入的文本)。

我没有探索过的两种可能方法:
  • 开始新的对话,而不是终止所有当前的IDialog与用户(新ConversationId)一起
  • 获取IDialogStack对象,并对其进行处理以管理对话框堆栈。

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

    最佳答案

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

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

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


  • BotFramework正在使用AutoFac作为DI容器
  • DialogModule 是它们的Autofac模块,用于对话框组件

  • 怎么做
    从上面知道 FACTS ,我的解决方案是
  • 注册依赖项,以便我们可以在 Controller 中使用:
  • // 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);
    
  • 获取 Autofac容器(可随意在您喜欢的代码中放置任何地方)
  • private static ILifetimeScope Container
    {
        get
        {
            var config = GlobalConfiguration.Configuration;
            var resolver = (AutofacWebApiDependencyResolver)config.DependencyResolver;
            return resolver.Container;
        }
    }
    
  • BotData 加载到作用域
  • 加载 DialogStack
  • 重置 DialogStack
  • 将新的 BotData 推回到 BotDataStore
  • using (var scope = DialogModule.BeginLifetimeScope(Container, activity))
    {
        var botData = scope.Resolve<IBotData>();
        await botData.LoadAsync(default(CancellationToken));
        var stack = scope.Resolve<IDialogStack>();
        stack.Reset();
        await botData.FlushAsync(default(CancellationToken));
    }
    
    希望能帮助到你。

    更新1(27/08/2016)
    感谢@ejadib指出,容器已经在 session 类中公开了。
    我们可以删除上面答案中的第2步,最后代码看起来像
    using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
    {
        var botData = scope.Resolve<IBotData>();
        await botData.LoadAsync(default(CancellationToken));
        var stack = scope.Resolve<IDialogStack>();
        stack.Reset();
        await botData.FlushAsync(default(CancellationToken));
    }
    

    关于c# - 当用户键入 “exit”, “quit”等时,终止所有对话并退出MS Bot Framework中的对话,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39113403/

    10-15 18:37