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

Posted

技术标签:

【中文标题】[BotFramework]:如何在瀑布对话框中捕获/提取通过 C# 网络聊天机器人中呈现的自适应卡片提交的值?【英文标题】:[BotFramework]: How to capture/extract the values submitted through Adaptive card rendered in C# Web Chat bot in a waterfall dialog? 【发布时间】:2019-09-24 00:51:22 【问题描述】:

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

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

语言:C#

机器人 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 步: 我想提取或捕获价值?怎么做?

【问题讨论】:

自适应卡在瀑布对话框中尚未真正得到支持。这是此请求的 [GitHub 问题] (github.com/Microsoft/botbuilder-dotnet/issues/614) 跟踪。有一些解决方案涉及创建您自己的卡片提示,例如在 [这里] (***.com/questions/53009106/…) 讨论的那个 @EdBoykin 澄清:瀑布对话框中绝对支持自适应卡片。他们只是目前不能用作提示,因为这并不是他们的初衷。但是,它们仍然可以显示。 我同意。我应该更清楚我的陈述。感谢您的澄清。 【参考方案1】:

通过 Waterfall Dialogs 使用自适应卡片

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

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

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

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

在您的瀑布对话框类中(步骤 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();
    

在您的主机器人类 (&lt;your-bot&gt;.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);

附加上下文

自适应卡片发送的提交结果与常规用户文本略有不同。当用户在聊天中键入并发送正常消息时,它会以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”并点击提交,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 发送的,这意味着提交数据不会作为对话的一部分出现在聊天窗口中,而是保留在自适应卡片上。

【讨论】:

谢谢理查森,但由于我对编码和机器人有点陌生,你能告诉我以下内容吗? 1. 你是如何获得/如何获得这个方法是 GetReplyFromCardAsync in var reply = await stepContext.Context.Activity.GetReplyFromCardAsync("BusinessyForm");当我尝试这个时,我没有得到方法? 2、我们在GetReplyFromCardAsync方法中传递的值“BusinessyForm”是什么?是自适应卡片json文件吗?3、GetReplyFromCardAsync方法是做什么的,如何使用Context.Activity访问它? @ChaitanyaNG 我很抱歉。我从我之前提供的另一个答案中复制/粘贴了答案,并且没有足够仔细地校对它。该方法是特定于他们的代码的。相反,请使用stepContext.Context.Activity.CreateReply(),我已将其编辑到我的答案中 您好,理查森,抱歉,因为我正在度假,所以无法尽快回复。我已经厌倦了您在瀑布对话框中解释的内容: 1. 第 1 步:我编写了显示您给出的自适应卡的代码,即显示自适应卡 2. 第 2 步:您解释的以下内容:等待 stepContext.Context.SendActivityAsync($"INPUT: stepContext.Result");返回等待 stepContext.NextAsync(); 3. 然后在初始化对话框上下文后的 OnTurnSync 方法中编写 Postback 活动的代码。但没有运气,仍然是同样的问题。请帮助。 @ChaitanyaNG 没问题。你能用你的代码编辑你的问题吗?它将帮助我了解发生了什么问题。或者,如果您可以发布指向您的存储库的链接,那也可以。 嗨,理查森,再次感谢您的光临。我已在以下 GIT 存储库中将我的解决方案上传到 ZIP 文件中:github.com/chaitanya116/AdaptivecardDatainV4Chatbot.git 如果您对该文件有任何问题,请告诉我。如果我的代码有任何问题,请逐步指导我。再次感谢您的帮助。

以上是关于[BotFramework]:如何在瀑布对话框中捕获/提取通过 C# 网络聊天机器人中呈现的自适应卡片提交的值?的主要内容,如果未能解决你的问题,请参考以下文章

Bot Framework:如何退出对话?

BotBuilder Nodejs示例查看

在一定时间后取消提示或对话框 - Bot Framework

如何在自适应对话框 HttpRequest 中从 xml 转换为 json?

如何在 Bot Framework 的测试函数中访问用户和对话数据

microsoft botframework bot 如何在自适应卡片中提及用户?