Bot Framework v4: ошибка при переходе к следующему шагу
Я хочу, чтобы мой бот спросил у пользователя местоположение. И когда пользователь отвечает "Рядом со мной", бот должен перейти к следующему шагу, а когда пользователь отвечает "Где-то еще", бот должен спросить пользователя о конкретном месте, прежде чем перейти к следующему шагу. Как бы то ни было, у меня ошибка в эмуляторе бота. Когда пользователь выбирает "Рядом со мной" или "Где-то еще", он не отправляет.
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 ответ
Ну, здесь есть пара проблем...
Во-первых, вам понадобится if/else на этапе, который имеет дело с "Near me"
против "Somewhere else"
потому что вы только хотите подсказать в случае "Где-то еще", верно?
Во-вторых, поскольку этот шаг теперь будет возвращать разные результаты в зависимости от выбранного пути, этот следующий шаг должен быть готов к обработке с различными входящими результатами. Прямо сейчас этот последний шаг прослушивается, потому что в настоящее время предполагается, что он получит FoundChoice
, но это не так. Было бы либо получить текст от textPrompt
в случае "Somewhere else"
путь или он ничего не получил бы из-за руководства ContinueDialog
вызов. Я на самом деле даже не уверен, что это работает, но, даже если это так, было бы более "правильным" использовать WaterfallStepContext::NextAsync()
API для продвижения водопада вместо этого. Посмотрите на следующие изменения для третьего шага для начинающих:
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()
});
});
Я должен также указать, что есть НАМНОГО более чистых / более простых способов сделать это без использования средств доступа к состоянию вообще. Вы действительно должны хранить промежуточные значения, которые вы собираете во время потока вашего водопада в WaterfallStepContext::Values
собственность вместо.