[BotFramework]:如何在瀑布对话框中捕获/提取通过C#Web聊天bot中呈现的自适应卡提交的值?

时间:2019-05-06 11:27:10

标签: c# botframework bots chatbot

我使用C#使用SDK 4在C#中创建了聊天机器人,该聊天机器人具有多个对话框,每个对话框都调用另一个对话框,在一个对话框中,我正在STEP#1中渲染自适应卡,该卡只有2个输入,并带有“确定”按钮: 1.日期 2.时间 3.确定按钮 这样我就可以提取/捕获通过STEP#2中的“确定”按钮提交的值并继续进行处理。

问题:如何在C#的瀑布对话框中提取在STEP#2的步骤1中提交的值?

语言:C#

Bot SDK:V4

请提供逐步指南,以帮助我成为BOT和编码新手?

我已经尝试了一些方法,例如: 1.将渲染的卡片放入提示 2.尝试通过以下方式提取/获取价值: stepContext.Context.Activity.Value

所有这些都无济于事。

步骤1: var cardAttachment = CreateAdaptiveCardAttachment(this.cards); var reply = stepContext.Context.Activity.CreateReply(); reply.Attachments = new List<Attachment>() { cardAttachment }; return await stepContext.Context.SendActivityAsync(reply); // 要么 return await stepContext.PromptAsync("datetextPrompt", new PromptOptions()  { Prompt = reply,  });

步骤2: 我想提取或获取价值?怎么做?

1 个答案:

答案 0 :(得分:0)

将自适应卡与Waterfall Dialogs 一起使用

从本质上讲,自适应卡不能像提示一样工作。带有提示,提示将显示并等待用户输入,然后继续。但是对于自适应卡(即使其中包含一个输入框和一个提交按钮),自适应卡中也没有代码,该代码将导致瀑布对话框在继续对话框之前先等待用户输入。

因此,如果您使用的是接受用户输入的自适应卡,则通常要处理用户在“瀑布对话框”上下文之外提交的所有内容。

话虽如此,如果您想在瀑布对话框中使用自适应卡,则有一种解决方法。基本上,您:

  1. 显示自适应卡
  2. 显示文字提示
  3. 将用户的自适应卡输入转换为文本提示输入

在“瀑布对话框”类中(步骤1和2):

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <template class="TestWindow" parent="GtkApplicationWindow">
    <property name="can_focus">False</property>
    <property name="default_width">600</property>
    <property name="default_height">300</property>
    <child type="titlebar">
      <placeholder/>
    </child>
    <child>
      <object class="GtkBox">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkLabel" id="label">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="label" translatable="yes">label</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkButton" id="button">
            <property name="label" translatable="yes">button</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
        <child>
          <placeholder/>
        </child>
      </object>
    </child>
  </template>
</interface>

在您的主要漫游器类( private async Task<DialogTurnResult> DisplayCardAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { // Display the Adaptive Card var reply = await stepContext.Context.Activity.CreateReply(); 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()之前的某个位置(步骤3):

await dialogContext.ContinueDialogAsync(cancellationToken)

其他上下文

自适应卡发送的“提交”结果与常规用户文本略有不同。当用户键入聊天并发送普通消息时,它最终以 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); } } } 结尾。当用户填写自适应卡上的输入时,它会以Context.Activity.Text结尾,该对象是键名是卡中的Context.Activity.Value,而值是自适应卡中的字段值卡。

例如json:

id

..创建一张看起来像这样的卡片:

Test Adaptive Card

如果用户在文本框中输入“ Testing Testing 123”,然后单击Submit,则{ "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" } 将类似于:

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' } 中看到用户提交的内容。

请注意,自适应卡的提交是作为postBack发送的(在Context.Activity.Value.userText中可见),这意味着提交数据不会在对话的一部分中显示在聊天窗口中,而是保留在自适应卡上