Bot Framework v4: ошибка при переходе к следующему шагу - PullRequest
0 голосов
/ 03 января 2019

Я хочу, чтобы мой бот спросил у пользователя местоположение.И когда пользователь отвечает «Рядом со мной», бот должен перейти к следующему шагу, а когда пользователь отвечает «Где-то еще», бот должен спросить пользователя о конкретном месте, прежде чем перейти к следующему шагу.Как бы то ни было, у меня ошибка в эмуляторе бота.Когда пользователь выбирает «Рядом со мной» или «Где-то еще», он не отправляет.

namespace FinancialPlannerBot.Dialogs.RealEstate
{
public class MainRealEstateDialog : WaterfallDialog
{
    public MainRealEstateDialog(string dialogId, IEnumerable<WaterfallStep> steps = null) : base(dialogId, steps)
    {
        AddStep(async (stepContext, cancellationToken) =>
        {
            return await stepContext.PromptAsync("choicePrompt",
               new PromptOptions
               {
                   Prompt = stepContext.Context.Activity.CreateReply("Would you like to buy or rent?"),
                   Choices = new[] {new Choice {Value = "Buy"},
                                    new Choice {Value = "Rent"}
                   }.ToList()
               });
        });

        AddStep(async (stepContext, cancellationToken) =>
        {              

            var buyOrRent = stepContext.Result as FoundChoice;
            var state = await (stepContext.Context.TurnState["FPBotAccessors"] as FPBotAccessors).FPBotStateAccessor.GetAsync(stepContext.Context);
            state.BuyOrRent = buyOrRent.Value;

            return await stepContext.PromptAsync("choicePrompt",
               new PromptOptions
               {
                   Prompt = stepContext.Context.Activity.CreateReply("What kind of real estate do you want?"),
                   Choices = new[] {new Choice {Value = "Type 1"},
                                    new Choice {Value = "Type 2"},
                                    new Choice {Value = "Type 3"}
                   }.ToList()
               });

        });

        AddStep(async (stepContext, cancellationToken) =>
        {
            var realEstateType = stepContext.Result as FoundChoice;
            var state = await (stepContext.Context.TurnState["FPBotAccessors"] as FPBotAccessors).FPBotStateAccessor.GetAsync(stepContext.Context);
            state.RealEstateType = realEstateType.Value;

            return await stepContext.PromptAsync("choicePrompt",
               new PromptOptions
               {
                   Prompt = stepContext.Context.Activity.CreateReply("Which location are you considering?"),
                   Choices = new[] {new Choice {Value = "Near me"},
                                    new Choice {Value = "Somewhere else"}
                   }.ToList()
               });
        });

        AddStep(async (stepContext, cancellationToken) => //ERROR
        {
            var nearOrSomewhereElse = stepContext.Result as FoundChoice;
            var state = await (stepContext.Context.TurnState["FPBotAccessors"] as FPBotAccessors).FPBotStateAccessor.GetAsync(stepContext.Context);
            state.NearOrSomewhereElse = nearOrSomewhereElse.Value;

            if (state.NearOrSomewhereElse == "Somewhere else")
            {
                await stepContext.PromptAsync("textPrompt",
                new PromptOptions
                {
                    Prompt = stepContext.Context.Activity.CreateReply("Which location are you considering?")
                });
            }

            return await stepContext.ContinueDialogAsync();
        });

        AddStep(async (stepContext, cancellationToken) =>
        {
            var nearOrSomewhereElse = stepContext.Result as FoundChoice;
            var state = await (stepContext.Context.TurnState["FPBotAccessors"] as FPBotAccessors).FPBotStateAccessor.GetAsync(stepContext.Context);
            state.NearOrSomewhereElse = nearOrSomewhereElse.Value;

            return await stepContext.PromptAsync("choicePrompt",
             new PromptOptions
                 {
                   Prompt = stepContext.Context.Activity.CreateReply($"Please indicate the size of {state.RealEstateType}"),
                   Choices = new[] {new Choice {Value = "Size 1"},
                                    new Choice {Value = "Size 2"},
                                    new Choice {Value = "Size 3"}
                   }.ToList()
             });                    

        });

    }

    public static string Id = "MainRealEstateDialog";
    public static MainRealEstateDialog Instance { get; }= new MainRealEstateDialog(Id);
}

}

1 Ответ

0 голосов
/ 04 января 2019

Ну, здесь есть пара проблем ...

Во-первых, вам понадобится if / else на шаге, который имеет дело с "Near me" против "Somewhere else", потому что вы хотите только запроситьв случае «Где-то еще», верно?

Во-вторых, поскольку этот шаг теперь будет возвращать разные результаты в зависимости от выбранного пути, этот следующий шаг должен быть готов к обработке с различными входящими результатами.Прямо сейчас этот последний шаг прослушивается, потому что в настоящее время предполагается, что он получит FoundChoice, но не получит.Он либо получит текст от textPrompt в случае "Somewhere else" path , либо , но ничего не получит из-за ручного вызова ContinueDialog.На самом деле я даже не уверен, что это работает, но, даже если это произойдет, было бы более «правильно» использовать API WaterfallStepContext::NextAsync() для продвижения водопада.Посмотрите на следующие изменения в третьем шаге для начинающих:

    AddStep(async (stepContext, cancellationToken) => //ERROR
    {
        var nearOrSomewhereElse = stepContext.Result as FoundChoice;
        var state = await (stepContext.Context.TurnState["FPBotAccessors"] as FPBotAccessors).FPBotStateAccessor.GetAsync(stepContext.Context);
        state.NearOrSomewhereElse = nearOrSomewhereElse.Value;

        if (state.NearOrSomewhereElse == "Somewhere else")
        {
            await stepContext.PromptAsync("textPrompt",
            new PromptOptions
            {
                Prompt = stepContext.Context.Activity.CreateReply("Which location are you considering?")
            });
        }
        else
        {
          await stepContext.NextAsync();
        }
    });

Хорошо, теперь вот изменения, которые вам необходимо внести в следующий шаг:

        AddStep(async (stepContext, cancellationToken) =>
        {
            var nearOrSomewhereElse = await (stepContext.Context.TurnState["FPBotAccessors"] as FPBotAccessors).FPBotStateAccessor.GetAsync(stepContext.Context).NearOrSomewhereElse;

            // If it's somewhere else, then this step need to get the text value the person was prompted for in the previous step
            if(nearOrSomewhereElse.Value == "Somewhere else")
            {
               // Get the result of the text prompt from the previous step
               var whereExactly = stepContext.Result as string;

               // TODO: store the value in your state so you can reference it later in the final search
            }

            return await stepContext.PromptAsync("choicePrompt",
             new PromptOptions
                 {
                   Prompt = stepContext.Context.Activity.CreateReply($"Please indicate the size of {state.RealEstateType}"),
                   Choices = new[] {new Choice {Value = "Size 1"},
                                    new Choice {Value = "Size 2"},
                                    new Choice {Value = "Size 3"}
                   }.ToList()
             });                    

        });

Я также должен отметить, что есть MUCH более чистых / простых способов сделать это без использования средств доступа к состоянию вообще.Вы действительно должны хранить промежуточные значения, которые вы собираете во время потока вашего водопада, в свойство WaterfallStepContext::Values.

...