我正在使用Bot框架V4.3,我一直在瀑布对话框中使用自适应卡,以获取用户信息,我希望在用户单击“提交”按钮后获取值,并且我想返回上一步如果用户单击“后退”按钮。
这是我的自适应卡的样子
我尝试了@mdrichardson在Stack Overflow中给出的解决方案 但是自适应卡会再次提示。
下面的代码帮助我们返回上一步,但如何将其实现到自适应卡的后退按钮上。
stepContext.ActiveDialog.State["stepIndex"] =(int)stepContext.ActiveDialog.State["stepIndex"] - 2;
将自适应卡添加到对话框。 我什至用TextPrompt代替ChoicePrompt
AddDialog(new ChoicePrompt("AdaptiveCardPrompt") { Style = ListStyle.None });
这就是我显示自适应卡的方式。我的自适应卡为Json格式
cardAttachment = CreateAdaptiveCardAttachment();
return await stepContext.PromptAsync("AdaptiveCardPrompt",
new PromptOptions
{
Prompt = (Activity)MessageFactory.Attachment(new Attachment
{
ContentType = AdaptiveCard.ContentType,
Content = cardAttachment.Content
}),
}, cancellationToken);
请帮助我解决此问题。预先谢谢你
编辑1 :@mdrichardson这是我设置对话框调用的方式
public static async Task Run(this Dialog dialog, ITurnContext turnContext,IStatePropertyAccessor<DialogState> accessor, CancellationToken cancellationToken = default(CancellationToken))
{
var dialogSet = new DialogSet(accessor);
dialogSet.Add(dialog);
var dialogContext = await dialogSet.CreateContextAsync(turnContext, cancellationToken);
// Ensure that message is a postBack (like a submission from Adaptive Cards)
if (dialogContext.Context.Activity.GetType().GetProperty("ChannelData") != null)
{
var channelData = JObject.Parse(dialogContext.Context.Activity.ChannelData.ToString());
if (channelData.ContainsKey("postBack"))
{
var postbackActivity = dialogContext.Context.Activity;
// Convert the user's Adaptive Card input into the input of a Text Prompt
// Must be sent as a string
postbackActivity.Text = postbackActivity.Value.ToString();
await dialogContext.Context.SendActivityAsync(postbackActivity);
}
}
var results = await dialogContext.ContinueDialogAsync(cancellationToken);
if (results.Status == DialogTurnStatus.Empty)
{
await dialogContext.BeginDialogAsync(dialog.Id, null, cancellationToken);
}
}
在OnTurnAsync
方法中
if (turnContext.Activity.Type == ActivityTypes.Message)
{
await Dialog.Run(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
}
编辑2 :我修改了代码,可以转到下一个瀑布步骤。但是我在这里面临另一个问题。 下一个提示没有显示,但我可以在日志中看到它 这就是它在模拟器中的显示方式
一旦用户单击MoreInfoAsync
方法中的按钮控件着陆点
private async Task<DialogTurnResult> MoreInfoAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
var goback = JObject.Parse(stepContext.Result.ToString());
stepContext.Values["AdaptiveCardDetails"] = stepContext.Result.ToString();
if (goback.ContainsKey("goBack"))
{
return await stepContext.ReplaceDialogAsync(InitialDialogId);
}
// stepContext.ActiveDialog.State["stepIndex"] = (int)stepContext.ActiveDialog.State["stepIndex"] - 2;
else
return await stepContext.PromptAsync("MoreInfo", new PromptOptions { Prompt = MessageFactory.Text("Tell Me more.") }, cancellationToken);
}
我想进入初始对话框,所以我正在使用ReplaceDialogAsync
。
MoreInfo
对话框未显示在模拟器中,但显示在日志中
编辑3 :这是瀑布台阶的完整代码
// This array defines how the Waterfall will execute.
var waterfallSteps = new WaterfallStep[]
{
ChoiceAsync,
CardAsync,
MoreInfoAsync,
ConfirmAsync
};
AddDialog(new WaterfallDialog(nameof(WaterfallDialog), waterfallSteps));
AddDialog(new ChoicePrompt("ChoiceType"));
AddDialog(new TextPrompt("AdaptiveCardPrompt"));
AddDialog(new TextPrompt("MoreInfo"));
InitialDialogId = nameof(WaterfallDialog);
private async Task<DialogTurnResult> ChoiceAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
options = new PromptOptions()
{
Prompt = MessageFactory.Text("Select the Choice"),
RetryPrompt = MessageFactory.Text("That was not a valid choice."),
Choices = GetChoices(),
Style = ListStyle.HeroCard
};
return await stepContext.PromptAsync("ChoiceType", options, cancellationToken);
}
private async Task<DialogTurnResult> CardAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
var cardAttachment = new Attachment();
stepContext.Values["leaveType"] = stepContext.Result.ToString();
cardAttachment = CreateAdaptiveCardAttachment();
return await stepContext.PromptAsync("AdaptiveCardPrompt",
new PromptOptions
{
Prompt = (Activity)MessageFactory.Attachment(new Attachment
{
ContentType = AdaptiveCard.ContentType,
Content = cardAttachment.Content,
}),
}, cancellationToken);
}
private async Task<DialogTurnResult> MoreInfoAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
var goback = JObject.Parse(stepContext.Result.ToString());
stepContext.Values["AdaptiveCardDetails"] = stepContext.Result.ToString();
if (goback.ContainsKey("goBack"))
{
return await stepContext.ReplaceDialogAsync(InitialDialogId);
}
else return await stepContext.PromptAsync("MoreInfo", new PromptOptions { Prompt = MessageFactory.Text("Tell Me more.") }, cancellationToken);
}
private async Task<DialogTurnResult> ConfirmAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
stepContext.Values["MoreInfo"] = stepContext.Result;
//As of now I wouldn't perform any task here so I'll end
return await stepContext.EndDialogAsync();
}
答案 0 :(得分:0)
问题出在您的OnTurnAsync()
方法上:
if (turnContext.Activity.Type == ActivityTypes.Message)
{
await Dialog.Run(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
}
每次用户发送消息时,都会导致运行对话框的新实例。由于自适应卡输入是作为回发消息(仍然是消息)发送的,因此它将使对话框再次运行,从而再次提示用户。
如果您要从OnTurnAsync()
或OnMessageAsync()
运行对话框,则应该执行以下两项操作:
使用if / switch语句。例如,如果消息包含“帮助”,请运行“帮助对话框”,或者
启动一个对话框,该对话框保存用户响应并根据需要跳过步骤。您可以在Core Bot's Booking Dialog中看到一个示例。请注意,它如何在每一步中使用诸如bookingDetails.TravelDate = (string)stepContext.Result;
之类的内容来保存用户响应,并在提示诸如if (bookingDetails.TravelDate == null)
之类的提示之前检查它是否存在于上一步中。对于您来说,您可以存储userProfile.AdaptiveCardDetails
之类的东西。
要使后退按钮正常工作,假设您的自适应卡中的后退按钮看起来像这样:
{
"type": "Action.Submit",
"title": "Back",
"data": {
"goBack": "true",
}
},
当用户单击“返回”时,该机器人将收到带有以下内容的活动:
由于用户想返回而您不需要数据,因此您可以执行以下操作:
// Ensure that message is a postBack (like a submission from Adaptive Cards)
if (dc.Context.Activity.GetType().GetProperty("ChannelData") != null)
{
var channelData = JObject.Parse(dc.Context.Activity.ChannelData.ToString());
if (channelData.ContainsKey("postBack") && turnContext.Activity.Value.GetType().GetProperty("goBack"))
{
dc.Context.Activity.Text = "Back";
}
}
,然后在“对话”步骤中:
if (stepContext.Result == "Back")
{
stepContext.ActiveDialog.State["stepIndex"] = (int)stepContext.ActiveDialog.State["stepIndex"] - 2;
}