我如何获得自适应卡的结果?

How do i get the result of a adaptive card?

我正在尝试获取 AdaptiveCard 的结果。 我的机器人使用瀑布对话框。在一个 Waterfallstep 中,我向用户展示了一些带有时间和日期的房间。然后用户可以选择一个房间。我尝试如下所示。遗憾的是 activity 保持为空。如何获取自适应卡的结果

private async Task<DialogTurnResult> AfterChoice(WaterfallStepContext step, CancellationToken cancellationToken)
{
    if (step.Result is Activity activity && activity.Value != null && ((dynamic)activity.Value).chosenRoom is JValue chosenRoom)
    {
        dynamic requestedBooking = JsonConvert.DeserializeObject<ExpandoObject>((string)chosenRoom.Value);
        this.roomemail = requestedBooking.roomEmail;
        return await step.EndDialogAsync();
    }
    else
    {
        return await step.BeginDialogAsync(whatever, cancellationToken: cancellationToken);
    }
}

如何让用户选择?

自适应卡片发送的提交结果与常规用户文本略有不同。当用户输入聊天内容并发送一条普通消息时,它会以 Context.Activity.Text 结尾。当用户在 Adaptive Card 上填写输入时,它以 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" 并点击提交,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.

请注意,自适应卡片提交是作为回发发送的,这意味着提交数据不会作为对话的一部分出现在聊天 window 中——它保留在自适应卡片上。

使用自适应卡片 Waterfall Dialogs

你的问题与此不太相关,但由于你最终可能会尝试这样做,我认为将其包含在我的回答中可能很重要。

自适应卡片本身不像提示那样工作。有了提示,提示将显示并等待用户输入,然后再继续。但是对于自适应卡片(即使它包含一个输入框和一个提交按钮),自适应卡片中没有代码会导致瀑布对话框在继续对话框之前等待用户输入。

因此,如果您使用的是接受用户输入的自适应卡片,您通常希望处理用户在 Waterfall Dialog 上下文之外提交的任何内容。

也就是说,如果您想将自适应卡片用作瀑布对话框的一部分,则有一个解决方法。基本上,你:

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

在瀑布对话框中 class(步骤 1 和 2):

private async Task<DialogTurnResult> DisplayCardAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    // Create 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),
    };

    // Create the text prompt
    var opts = new PromptOptions
    {
        Prompt = new Activity
        {
            Attachments = new List<Attachment>() { cardAttachment },
            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();
}

在您的主机器人中 class (<your-bot>.cs)(第 3 步):

var activity = turnContext.Activity;

if (string.IsNullOrWhiteSpace(activity.Text) && activity.Value != null)
{
    activity.Text = JsonConvert.SerializeObject(activity.Value);
}