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);
        }
      }
    }
Другие вопросы по тегам