ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c#-如何在随后的瀑布步骤中检索自适应卡的表单提交

2019-11-08 07:07:12  阅读:237  来源: 互联网

标签:botframework bots c


我使用的是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);

但是在这种情况下,我不想提示用户其他信息.理想情况下,我想“保持”对话框状态以进行响应,当检测到响应时,下一步将处理提交结果.

我尝试过的事情:

>已查看示例herehere.两者都显示了如何渲染卡片,但没有显示如何在后续步骤中处理输入.
>已查看输入here的卡架构文档.
>在GitHub的AdaptiveCard存储库here中审查了关于类似问题的讨论.

这可行吗?任何帮助将非常感激!

解决方法:

自适应卡发送的“提交”结果与常规用户文本略有不同.当用户键入聊天并发送正常消息时,它最终以Context.Activity.Text结尾.当用户填写自适应卡上的输入时,它会以Context.Activity.Value结尾,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"
}

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

Test Adaptive Card

如果用户在文本框中输入“ 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()下,在等待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);
            }
        }            
    }

标签:botframework,bots,c
来源: https://codeday.me/bug/20191108/2006256.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有