C# 当用户键入“时,终止所有对话框并退出MS Bot Framework中的对话”;退出“&引用;“退出”;等
我不知道如何在MS Bot框架中完成一件非常简单的事情:允许用户中断任何对话,离开当前对话框并通过键入“退出”、“退出”或“重新开始”返回主菜单 以下是我的主要对话的安排方式:C# 当用户键入“时,终止所有对话框并退出MS Bot Framework中的对话”;退出“&引用;“退出”;等,c#,bots,botframework,C#,Bots,Botframework,我不知道如何在MS Bot框架中完成一件非常简单的事情:允许用户中断任何对话,离开当前对话框并通过键入“退出”、“退出”或“重新开始”返回主菜单 以下是我的主要对话的安排方式: public async Task<HttpResponseMessage> Post([FromBody]Activity activity) { try { if (activity.Type == ActivityTypes.Mes
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);
}
}
公共异步任务发布([FromBody]活动)
{
尝试
{
if(activity.Type==ActivityTypes.Message)
{
LogUserBehavior(活动);
if(activity.Text.ToLower()=“重新开始”)
{
//在这里做点什么,但我这里没有IDialogContext!
}
BotUtils.SendTyping(活动);//在收到每条消息时发送“typing”指示符
wait Conversation.sendaync(活动,()=>newrootdialog());
}
其他的
{
HandleSystemMessage(活动);
}
}
我知道如何使用context.Done(this);
终止对话框,但在这种方法中,我没有访问IDialogContext对象的权限,因此无法调用.Done()
当用户键入某条消息时,除了在所有对话框的每个步骤中添加检查外,还有其他方法终止整个对话框堆栈吗
发布赏金:
我需要一种方法来终止所有IDialog
s,而不使用我在这里发布的骇人听闻的黑客(它删除我需要的所有用户数据,例如用户设置和首选项)
基本上,当用户键入“退出”或“退出”时,我需要退出当前正在进行的任何IDialog
,并返回到新状态,就像用户刚刚启动了一个对话一样
我需要能够从MessageController.cs,
中执行此操作,在那里我仍然无法访问IDialogContext
。我在那里似乎唯一有用的数据是活动
对象。如果有人指出其他方法,我会很高兴
另一种方法是找到其他方法,在bot的其他位置检查“exit”和“quit”关键字,而不是在Post方法中
但这不应该是在IDialog
的每一步都要进行的检查,因为这太多代码,甚至不总是可能的(当使用PrompDialog
时,我无法访问用户键入的文本)
我没有探索的两种可能的方法:
- 开始新的对话,而不是终止所有当前的
s 与用户(新建IDialog
)会话ID
- 获取
对象,并对其执行一些操作以管理对话框堆栈IDialogStack
Microsoft文档对此对象没有提示,因此我不知道如何获取它。我不使用允许
.Switch()的链
对象
在bot中的任何地方,但是如果您认为可以重写它来使用它,它也可以是解决这个问题的方法之一。但是,我还没有找到如何在各种类型的对话框之间进行分支(FormFlow
和普通的IDialog
)然后调用自己的子对话框等。这是一个非常丑陋的黑客程序。它基本上删除了所有用户数据(您可能确实需要这些数据),这会导致对话重新启动
如果有人知道更好的方法,在不删除用户数据的情况下,请分享
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);
}
}
公共异步任务发布([FromBody]活动)
{
尝试
{
if(activity.Type==ActivityTypes.Message)
{
//如果用户键入某些消息,请退出所有对话框并重新开始
字符串msg=activity.Text.ToLower().Trim();
如果(msg==“重新开始”| | msg==“退出”| | msg==“退出”| | msg==“完成”| | msg==“重新启动”| | msg==“离开”| msg==“重置”)
{
//这就是重新设置对话的地方!
activity.GetStateClient().BotState.DeleteStateForUser(activity.ChannelId,activity.From.Id);
}
//即使我们重置了所有内容,也要再次显示欢迎信息
BotUtils.SendTyping(活动);//在收到每条消息时发送“typing”指示符
wait Conversation.sendaync(活动,()=>newrootdialog());
}
其他的
{
HandleSystemMessage(活动);
}
}
问题分解
根据我对您问题的理解,您想要实现的是在不完全破坏bot状态的情况下重置对话框堆栈
事实(我从github存储库中读到)
如何做 从上面了解事实,我的解决方案是
使用(var scope=DialogModule.BeginLifetimeScope(容器,活动))
{
var botData=scope.Resolve();
等待botData.LoadAsync(默认值(CancellationToken));
var stack=scope.Resolve();
// 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);
private static ILifetimeScope Container
{
get
{
var config = GlobalConfiguration.Configuration;
var resolver = (AutofacWebApiDependencyResolver)config.DependencyResolver;
return resolver.Container;
}
}
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));
}
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));
}
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);
}