编辑:Drew 的回答是正确的,但我的回答提供了另一种潜在的解决方案。您可以在此处找到更多信息:Managing State。特别是:
用户状态在机器人与之交谈的任何时候都可用
该频道上的该用户,无论对话如何
状态在特定对话中的任何时候都可用,无论
用户(即群组对话)私人对话状态为
范围既适用于特定对话,也适用于该特定用户
提示
用户状态和会话状态都由频道限定。相同
使用不同渠道访问您的机器人的人显示为
不同的用户,每个频道一个,每个都有不同的用户
状态。
其他解决方案
如果您能够指定 from Id,但不能确保 conversation Id 保持不变(见下文,陷阱下方),则此解决方案最适合。
您可以在他们的UserState 中保存用户正在执行的步骤。
基本机器人
BasicBot 使用它的 GreetingState 类来做到这一点。
来自其GreetingDialog:
在第一步中,它初始化GreetingState,它通过查看已经设置了哪些用户变量来跟踪用户在对话框中的进度:
private async Task<DialogTurnResult> InitializeStateStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
var greetingState = await UserProfileAccessor.GetAsync(stepContext.Context, () => null);
if (greetingState == null)
{
var greetingStateOpt = stepContext.Options as GreetingState;
if (greetingStateOpt != null)
{
await UserProfileAccessor.SetAsync(stepContext.Context, greetingStateOpt);
}
else
{
await UserProfileAccessor.SetAsync(stepContext.Context, new GreetingState());
}
}
return await stepContext.NextAsync();
}
然后在每一步中,它都会加载GreetingState:
var greetingState = await UserProfileAccessor.GetAsync(stepContext.Context);
并检查该步骤是否已经完成,例如:
if (greetingState != null && !string.IsNullOrWhiteSpace(greetingState.Name) && !string.IsNullOrWhiteSpace(greetingState.City))
如果没有greetingState 或.Name 或.City 存在,则提示输入,如果已填写,则继续:
return await stepContext.NextAsync();
在每一步,它都会保存到GreetingState,如下所示:
greetingState.Name = char.ToUpper(lowerCaseName[0]) + lowerCaseName.Substring(1);
await UserProfileAccessor.SetAsync(stepContext.Context, greetingState);
为您的用例简化
对你来说,如果你不需要保存用户信息,你可以创建一个简单的Step类:
{
/// <summary>
/// User state properties for Waterfall Step.
/// </summary>
public class Step
{
public string StepNumber { get; set; }
}
}
开始你的瀑布对话框:
private async Task<DialogTurnResult> InitializeStateStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
var StepState = await UserProfileAccessor.GetAsync(stepContext.Context, () => null);
if (StepState == null)
{
var StepStateOpt = stepContext.Options as StepState;
if (StepStateOpt != null)
{
await UserProfileAccessor.SetAsync(stepContext.Context, StepStateOpt );
}
else
{
await UserProfileAccessor.SetAsync(stepContext.Context, new StepState());
}
}
return await stepContext.NextAsync();
}
在每一步,加载当前的Step:
var stepState = await UserProfileAccessor.GetAsync(stepContext.Context);
检查他们是否已经超过当前步骤:
if (stepState.StepNumber <= 2)
{
// ...do stuff
// Save that user has completed step
stepState.StepNumber++;
await UserProfileAccessor.SetAsync(stepContext.Context, stepState);
}
else
{
return await stepContext.NextAsync();
}
陷阱
需要注意的几件大事:
UserState 仅针对相同的from ID 和channel ID 持续存在。确保离开瀑布中间的用户在重新输入时具有相同的from ID,并且他们从相同的channel 重新输入。这不是模拟器的默认设置——在模拟器中,当会话重新启动时,会创建一个新的from ID。 (注意:认为from ID 是User ID 的同义词。它只是来自Activity.From.Id)
ConversationState 仅针对相同的 conversation ID 和 channel ID 持续存在。 conversation ID 在频道内的持久性因频道而异。
有关不同 ID 的更多信息:ID fields in the Bot Framework。