[英]How to retrieve user entered input in adaptive card to the c# code and how to call next intent on submit button click
I have a date picker adaptive card which I call during an intent call. 我有一个日期选择器自适应卡,可以在意向通话中调用它。 I am not getting as to how can I get value entered by the user and pass it to my bot luis where I will be having an intent which will get triggered with those values
我不知道如何获取用户输入的值并将其传递给我的机器人路易斯,在那里我将有一个意图被这些值触发
I have tried parsing the adaptive card json but I want the updated json with user entered values in it on submit button click. 我尝试解析自适应卡json,但是我希望在提交按钮单击时使用用户输入的值来更新json。
private Attachment CreateAdaptiveCardAttachment()
{
// combine path for cross platform support
string[] paths = { ".", "Cards", "AddingLeaveDetails.json" };
string fullPath = Path.Combine(paths);
var adaptiveCard = File.ReadAllText(fullPath);
return new Attachment()
{
ContentType = "application/vnd.microsoft.card.adaptive",
Content = JsonConvert.DeserializeObject(adaptiveCard),
};
}
private Activity CreateResponse(IActivity activity, Attachment attachment)
{
var response = ((Activity)activity).CreateReply();
response.Attachments = new List<Attachment>() { attachmen`enter code here`t };
return response;
}
@NikhilBansal, You can skip the "Waterfall Dialog" part of this answer (it's more for posterity), and head to the "Capture User Input" section. @NikhilBansal,您可以跳过此答案的“瀑布对话框”部分(更多用于后代),然后转到“捕获用户输入”部分。 It will likely be helpful to read the "Additional Context" and "Additional Resources" links, as well.
同样,阅读“其他上下文”和“其他资源”链接也可能会有所帮助。
Natively, Adaptive Cards don't work like prompts. 本地,自适应卡不能像提示一样工作。 With a prompt, the prompt will display and wait for user input before continuing.
带有提示,提示将显示并等待用户输入,然后继续。 But with Adaptive Cards (even if it contains an input box and a submit button), there is no code in an Adaptive Card that will cause a Waterfall Dialog to wait for user input before continuing the dialog.
但是对于自适应卡(即使它包含一个输入框和一个提交按钮),自适应卡中也没有代码,这会使瀑布对话框在继续对话框之前先等待用户输入。
So, if you're using an Adaptive Card that takes user input, you generally want to handle whatever the user submits outside of the context of a Waterfall Dialog. 因此,如果您正在使用需要用户输入的自适应卡,则通常需要处理用户在“瀑布对话框”上下文之外提交的所有内容。
That being said, if you want to use an Adaptive Card as part of a Waterfall Dialog, there is a workaround. 话虽如此,如果您想在瀑布对话框中使用自适应卡,则有一种解决方法。 Basically, you:
基本上,您:
In your Waterfall Dialog class (steps 1 and 2): 在“瀑布对话框”类中(步骤1和2):
private async Task<DialogTurnResult> DisplayCardAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
// Display the Adaptive Card
var cardPath = Path.Combine(".", "AdaptiveCard.json");
var cardJson = File.ReadAllText(cardPath);
var cardAttachment = new Attachment()
{
ContentType = "application/vnd.microsoft.card.adaptive",
Content = JsonConvert.DeserializeObject(cardJson),
};
var message = MessageFactory.Text("");
message.Attachments = new List<Attachment>() { cardAttachment };
await stepContext.Context.SendActivityAsync(message, 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();
}
Capture User Input 捕获用户输入
In your main bot class ( <your-bot>.cs
), under OnTurnAsync()
, near the beginning of the method, somewhere before await dialogContext.ContinueDialogAsync(cancellationToken)
is called (step 3): 在您的主要bot类(
<your-bot>.cs
)中的OnTurnAsync()
,在该方法的开头附近,在await dialogContext.ContinueDialogAsync(cancellationToken)
之前的某个位置(步骤3):
var activity = turnContext.Activity;
if (string.IsNullOrWhiteSpace(activity.Text) && activity.Value != null)
{
activity.Text = JsonConvert.SerializeObject(activity.Value);
}
Update: For your code, specifically, you need to directly modify turnContext
before sending it to your recognizer. 更新:具体来说,对于您的代码,您需要在将
turnContext
发送到识别turnContext
之前直接对其进行修改。 Since RecognizeAsync
doesn't work with objects, we need to ensure we send the appropriate value. 由于
RecognizeAsync
不适用于对象,因此我们需要确保发送适当的值。 Something like: 就像是:
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
// Capture input from adaptive card
if (string.IsNullOrEmpty(turnContext.Activity.Text) && turnContext.Activity.Value != null)
{
// Conditionally convert based off of input ID of Adaptive Card
if ((turnContext.Activity.Value as JObject)["<adaptiveCardInputId>"] != null)
{
turnContext.Activity.Text = (turnContext.Activity.Value as JObject)["<adaptiveCardInputId>"].ToString();
}
}
// First, we use the dispatch model to determine which cognitive service (LUIS or QnA) to use.
var recognizerResult = await _botServices.Dispatch.RecognizeAsync(turnContext, cancellationToken);
// Top intent tell us which cognitive service to use.
var topIntent = recognizerResult.GetTopScoringIntent();
// Next, we call the dispatcher with the top intent.
await DispatchToTopIntentAsync(turnContext, topIntent.intent, recognizerResult, cancellationToken);
}
The reason the code two blocks above didn't work is just because it wasn't set up for your code. 上面两个代码块不起作用的原因仅仅是因为没有为您的代码设置代码。
RecognizeAsync
looks at turnContext.Activity.Text
, which is null for an adaptive card (since adaptive card inputs come in Activity.Value
. So, this new code sets turnContext.Activity.Text
to turnContext.Activity.Value
. However, to send it to the recognizer, you need it to be a string and not an object, so be sure to change <adaptiveCardInputId>
to whatever ID you have on your adaptive card. RecognizeAsync
查看turnContext.Activity.Text
,这对于自适应卡为null(因为自适应卡输入来自Activity.Value
。因此,此新代码将turnContext.Activity.Text
设置为turnContext.Activity.Value
,但是要发送它对于识别器,您需要将其作为字符串而不是对象,因此请确保将<adaptiveCardInputId>
更改为您在自适应卡上拥有的ID。
Adaptive Cards send their Submit results a little different than regular user text. 自适应卡发送的“提交”结果与常规用户文本略有不同。 When a user types in the chat and sends a normal message, it ends up in
Context.Activity.Text
. 当用户键入聊天并发送正常消息时,它最终出现在
Context.Activity.Text
。 When a user fills out an input on an Adaptive Card, it ends up in Context.Activity.Value
, which is an object where the key names are the id
in your card and the values are the field values in the adaptive card. 当用户填写自适应卡上的输入时,它会以
Context.Activity.Value
结尾,该对象是键名称是您卡中的id
,而值是自适应卡中的字段值的对象。
For example, the json: 例如,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"
}
.. creates a card that looks like: ..创建一张看起来像这样的卡片:
If a user enters "Testing Testing 123" in the text box and hits Submit, Context.Activity
will look something like: 如果用户在文本框中输入“ 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' }
The user submission can be seen in Context.Activity.Value.userText
. 用户提交可以在
Context.Activity.Value.userText
看到。
Note that adaptive card submissions are sent as a postBack, which means that the submission data doesn't appear in the chat window as part of the conversation--it stays on the Adaptive Card. 请注意,自适应卡提交是作为postBack发送的,这意味着提交数据不会作为对话的一部分出现在聊天窗口中,而是保留在自适应卡上。
AdaptiveCardPrompt
- This may be added to the SDK someday. AdaptiveCardPrompt
可能有一天会添加到SDK中。 In the meantime, you can use it as a development reference
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.