我正在使用Bot Framework(V4),并且有一个分为两个步骤的WaterfallDialog;第一步是捕获表单数据,第二步是处理表单数据。
第一步发送答复:
private async Task<DialogTurnResult> CaptureFormStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
var reply = await stepContext.Context.Activity.GetReplyFromCardAsync("BusinessyForm");
await stepContext.Context.SendActivityAsync(reply, cancellationToken);
}
GetReplyFromCardAsync
是一种扩展方法,它使用自适应卡作为附件来获取Activity
的JSON表示形式。自适应卡的格式类似于this。自适应卡还具有提交动作。
我的问题是如何将这些信息传递到下一步?
在先前的尝试中,我返回了提示:
return await stepContext.PromptAsync(
"custom-prompt-id",
new PromptOptions { Prompt = MessageFactory.Text("Hello!") },
cancellationToken);
但是在这种情况下,我不想提示用户其他信息。理想情况下,我想“保持”对话框状态以进行响应,当检测到响应时,下一步将处理提交结果。
我尝试过的事情:
这可行吗?任何帮助将不胜感激!
答案 0 :(得分:3)
自适应卡发送的“提交”结果与常规用户文本略有不同。当用户键入聊天并发送普通消息时,它最终以Context.Activity.Text
结尾。当用户填写自适应卡上的输入时,它会以Context.Activity.Value
结尾,该对象是键名是卡中的id
,而值是自适应卡中的字段值卡。
例如json:
{
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"text": "Test Adaptive Card"
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": "Text:"
}
],
"width": 20
},
{
"type": "Column",
"items": [
{
"type": "Input.Text",
"id": "userText",
"placeholder": "Enter Some Text"
}
],
"width": 80
}
]
}
],
"actions": [
{
"type": "Action.Submit",
"title": "Submit"
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.0"
}
..创建一张看起来像这样的卡片:
如果用户在文本框中输入“ Testing Testing 123”,然后单击Submit,则Context.Activity
将类似于:
{ type: 'message',
value: { userText: 'Testing Testing 123' },
from: { id: 'xxxxxxxx-05d4-478a-9daa-9b18c79bb66b', name: 'User' },
locale: '',
channelData: { postback: true },
channelId: 'emulator',
conversation: { id: 'xxxxxxxx-182b-11e9-be61-091ac0e3a4ac|livechat' },
id: 'xxxxxxxx-182b-11e9-ad8e-63b45e3ebfa7',
localTimestamp: 2019-01-14T18:39:21.000Z,
recipient: { id: '1', name: 'Bot', role: 'bot' },
timestamp: 2019-01-14T18:39:21.773Z,
serviceUrl: 'http://localhost:58453' }
可以在Context.Activity.Value.userText
中看到用户提交的内容。
请注意,自适应卡的提交是作为postBack发送的(在Context.Activity.ChannelData
中可见),这意味着提交数据不会在对话的一部分中显示在聊天窗口中,而是保留在自适应卡上
将自适应卡与Waterfall Dialogs 一起使用
从本质上讲,自适应卡不能像提示一样工作。带有提示,提示将显示并等待用户输入,然后继续。但是对于自适应卡(即使其中包含一个输入框和一个提交按钮),自适应卡中也没有代码,该代码将导致瀑布对话框在继续对话框之前先等待用户输入。
因此,如果您使用的是接受用户输入的自适应卡,则通常要处理用户在“瀑布对话框”上下文之外提交的所有内容。
话虽如此,如果您想在瀑布对话框中使用自适应卡,则有一种解决方法。基本上,您:
在“瀑布对话框”类中(步骤1和2):
private async Task<DialogTurnResult> DisplayCardAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
// Display the Adaptive Card
var reply = await stepContext.Context.Activity.GetReplyFromCardAsync("BusinessyForm");
await stepContext.Context.SendActivityAsync(reply, cancellationToken);
// Create the text prompt
var opts = new PromptOptions
{
Prompt = new Activity
{
Type = ActivityTypes.Message,
Text = "waiting for user input...", // You can comment this out if you don't want to display any text. Still works.
}
};
// Display a Text Prompt and wait for input
return await stepContext.PromptAsync(nameof(TextPrompt), opts);
}
private async Task<DialogTurnResult> HandleResponseAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
// Do something with step.result
// Adaptive Card submissions are objects, so you likely need to JObject.Parse(step.result)
await stepContext.Context.SendActivityAsync($"INPUT: {stepContext.Result}");
return await stepContext.NextAsync();
}
在您的主要漫游器类(<your-bot>.cs
中,在OnTurnAsync()
下,靠近方法开头的位置,调用了await dialogContext.ContinueDialogAsync(cancellationToken)
之前的某个位置(步骤3):
if (activity.Type == ActivityTypes.Message)
{
// 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"))
{
var postbackActivity = dc.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 dc.Context.SendActivityAsync(postbackActivity);
}
}
}
答案 1 :(得分:0)
这是nodejs版本:
您的bot.ts文件:
this.onTurn(async (context, next) => {
if (context.activity.type == ActivityTypes.Message) {
// Ensure that message is a postBack (like a submission from Adaptive Cards)
if (context.activity.channelData != null) {
if (context.activity.channelData.postBack === true) {
const postbackActivity = context.activity;
// Convert the user's Adaptive Card input into the input of a Text Prompt
// Must be sent as a string
postbackActivity.text = JSON.stringify(postbackActivity.value);
// context.activity.text = postbackActivity.value
await context.sendActivity(postbackActivity);
}
}
}
await next();
});