25 c# bots botframework
我无法弄清楚如何在MS Bot Framework中做一个非常简单的事情:允许用户打破任何对话,离开当前对话框并通过键入"quit","exit"或"返回主菜单"重来".
这是我的主要对话设置方式:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
我知道如何终止一个对话框context.Done<DialogType>(this);,但在这个方法中,我没有访问IDialogContext对象,所以我无法调用.Done().
当用户键入某个消息时,除了在所有对话框的每个步骤中添加一个检查之外,还有其他方法可以终止整个对话框堆栈吗?
发表赏金:
我需要一种方法来终止所有IDialogs而不使用我在这里发布的令人发指的黑客攻击(删除我需要的所有用户数据,例如用户设置和首选项).
基本上,当用户键入"退出"或"退出"时,我需要退出IDialog当前正在进行的任何操作并返回到新状态,就好像用户刚刚发起了对话一样.
我需要能够从MessageController.cs,我仍无法访问的地方执行此操作IDialogContext.我似乎唯一有用的数据是Activity对象.如果有人指出其他方法,我会很高兴.
另一种方法是找到一些其他方法来检查机器人的其他位置的"退出"和"退出"关键字,而不是在Post方法中.
但它不应该是在每一步都完成的检查IDialog,因为这是太多的代码,甚至不可能(当使用时PromptDialog,我无法访问用户输入的文本).
我没有探索的两种可能方式:
IDialogs,与用户开始新的对话(新ConversationId)IDialogStack对象并使用它来管理对话框堆栈.Microsoft文档对此对象保持沉默,因此我不知道如何获取它.我不使用Chain允许.Switch()机器人中任何位置的对象,但如果您认为可以重写它以使用它,它也可以是解决此问题的方法之一.但是,我还没有找到如何在各种类型的对话框(FormFlow和普通对象IDialog)之间进行分支,这些对话框又称为自己的子对话框等.
Kie*_*Chu 27
根据我对您的问题的理解,您想要实现的是重置对话框而不会完全破坏机器人状态.
BotDataStore> BotData> DialogStack
从上面了解FACTS,我的解决方案就是
// 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);
Run Code Online (Sandbox Code Playgroud)
private static ILifetimeScope Container
{
get
{
var config = GlobalConfiguration.Configuration;
var resolver = (AutofacWebApiDependencyResolver)config.DependencyResolver;
return resolver.Container;
}
}
Run Code Online (Sandbox Code Playgroud)
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));
}
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你.
感谢@ejadib指出,Container已经在会话类中公开了.
我们可以在上面的答案中删除第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));
}
Run Code Online (Sandbox Code Playgroud)
小智 9
这是一个非常难看的黑客行为.它基本上删除了所有用户数据(您可能实际需要),这会导致会话重新启动.
如果有人知道更好的方法,而不删除用户数据,请分享.
public async Task<HttpResponseMessage> 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);
}
}
Run Code Online (Sandbox Code Playgroud)