Bot Framework всегда запускает один и тот же метод диалога
Я играю с примерами Bot Framework и сделал простой диалог, который намеревается приветствовать пользователя. Проблема, с которой я столкнулся, заключается в том, что после запроса имени пользователя метод возобновления никогда не срабатывает. Он всегда возвращается к методу ConverstationStartedAsync. Есть идеи почему?
Это диалог:
public class HelloDialog : IDialog<string>
{
public async Task StartAsync(IDialogContext context)
{
context.Wait(ConversationStartedAsync);
}
public async Task ConversationStartedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
var message = await argument;
PromptDialog.Text(
context: context,
resume: AfterNameInput,
prompt: "Hi! what's your name?",
retry: "Sorry, I didn't get that.");
}
public async Task AfterNameInput(IDialogContext context, IAwaitable<string> result)
{
var name = await result;
PromptDialog.Text(context, AfterAskNeed, "Hi {name}. How can I help you?", "Sorry, I didn't get that.", 3);
}
и это действие в MessagesController:
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
if (activity != null)
{
// one of these will have an interface and process it
switch (activity.GetActivityType())
{
case ActivityTypes.Message:
try
{
await Conversation.SendAsync(activity, () => new HelloDialog());
}
catch(Exception ex)
{
}
break;
case ActivityTypes.ConversationUpdate:
case ActivityTypes.ContactRelationUpdate:
case ActivityTypes.Typing:
case ActivityTypes.DeleteUserData:
default:
break;
}
}
return new HttpResponseMessage(System.Net.HttpStatusCode.Accepted);
}
3 ответа
Я действительно не знаю, что произошло, но я мог бы решить эту проблему, удалив пакет Microsoft.Bot.Builder (v3.0), а затем обновив его до v3.3.3.
Это произошло для меня, когда я допустил ошибку в коде, затем исправил и повторно развернул код. Однако, поскольку Bot Framework сохраняет состояние, вы можете застрять, используя старую логику.
На Facebook вы можете перезапустить очистить сохраненное состояние, набрав /deleteprofile, а в эмуляторе просто создав новый диалог или закрыв / открыв эмулятор.
Как сказал MSDN ( https://docs.microsoft.com/en-us/bot-framework/dotnet/bot-builder-dotnet-manage-conversation-flow):
Жизненный цикл диалога
Когда диалог вызывается, он берет на себя управление потоком разговора. Каждое новое сообщение будет обрабатываться этим диалогом до тех пор, пока оно не закроется или не перенаправится в другое диалоговое окно. В C# вы можете использовать context.Wait(), чтобы указать обратный вызов для вызова в следующий раз, когда пользователь отправит сообщение. Чтобы закрыть диалог и удалить его из стека (тем самым отправив пользователя обратно в предыдущий диалог в стеке), используйте context.Done(). Вы должны заканчивать каждый метод диалога с помощью context.Wait(), context.Fail (), context.Done() или некоторой директивы перенаправления, такой как context.Forward () или context.Call (). Метод диалога, который не заканчивается ни одним из них, приведет к ошибке (потому что среда не знает, какое действие предпринять в следующий раз, когда пользователь отправит сообщение).
Решение состоит в том, чтобы изящно выйти из диалогового окна, полный код приведен ниже.
[Serializable]
public class RootDialog : IDialog<object>
{
public async Task StartAsync(IDialogContext context)
{
context.Wait(ConversationStartedAsync);
}
public async Task ConversationStartedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
var message = await argument;
PromptDialog.Text(
context: context,
resume: AfterNameInput,
prompt: "Hi! what's your name?",
retry: "Sorry, I didn't get that.");
}
public async Task AfterNameInput(IDialogContext context, IAwaitable<string> result)
{
var name = await result;
//Set value in the context, like holding value in ASP.NET Session
context.PrivateConversationData.SetValue<string>("Name", name);
PromptDialog.Choice(context, this.ResumeAfterTakingGender, new[] { "Male", "Female" }, "Please enter your gender", "I am sorry I didn't get that, try selecting one of the options below", 3);
}
private async Task ResumeAfterTakingGender(IDialogContext context, IAwaitable<string> result)
{
string gender = await result;
string name = string.Empty;
//Get the data from the context
context.PrivateConversationData.TryGetValue<string>("Name", out name);
await context.PostAsync($"Hi {name} you are a {gender}");
//Gracefully exit the dialog, because its implementing the IDialog<object>, so use
context.Done<object>(null);
}
}
}