C# 提交后,从自适应卡中检索数据而不重新显示卡的正确方法是什么?

C# 提交后,从自适应卡中检索数据而不重新显示卡的正确方法是什么?,c#,botframework,microsoft-teams,C#,Botframework,Microsoft Teams,我在我的带有瀑布对话框的机器人中使用自适应卡。我想检索用户在表单中提供的数据,并在用户单击submit按钮后在另一张自适应卡的chat中显示该数据。但当我点击提交按钮时,空卡片再次提示 我读过这篇文章,并尝试了回发通道数据的解决方案。它只在模拟器中工作,我可以检索所有数据。但当我将其部署到Azure和MSTeam频道时,每次单击后,它都会一次又一次地重新提示 我的OnTurnAsync方法: public override async Task OnTurnAsync(ITurnContext

我在我的带有瀑布对话框的机器人中使用自适应卡。我想检索用户在表单中提供的数据,并在用户单击submit按钮后在另一张自适应卡的chat中显示该数据。但当我点击提交按钮时,空卡片再次提示

我读过这篇文章,并尝试了回发通道数据的解决方案。它只在模拟器中工作,我可以检索所有数据。但当我将其部署到Azure和MSTeam频道时,每次单击后,它都会一次又一次地重新提示

我的OnTurnAsync方法:

public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {

            await base.OnTurnAsync(turnContext, cancellationToken);


            var activity = turnContext.Activity;

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

            }

            await ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
            await UserState.SaveChangesAsync(turnContext, false, cancellationToken);

        }
我的DialogExtensions.cs我从Gags08中获取了代码,它在emulator上工作得很好,但在团队中却不行:

using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Dialogs;
using Newtonsoft.Json.Linq;

namespace Microsoft.BotBuilderSamples
{
    public static class DialogExtensions
    {
        public static async Task Run(this Dialog dialog, ITurnContext turnContext, IStatePropertyAccessor<DialogState> accessor, CancellationToken cancellationToken = default(CancellationToken))
        {

            var dialogSet = new DialogSet(accessor);
            dialogSet.Add(dialog);


            var dialogContext = await dialogSet.CreateContextAsync(turnContext, cancellationToken);
            // Ensure that message is a postBack (like a submission from Adaptive Cards)
            if (dialogContext.Context.Activity.GetType().GetProperty("ChannelData") != null)
            {
                var channelData = JObject.Parse(dialogContext.Context.Activity.ChannelData.ToString());
                if (channelData.ContainsKey("postBack"))
                {
                    var postbackActivity = dialogContext.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 dialogContext.Context.SendActivityAsync(postbackActivity);
                }
            }
            var results = await dialogContext.ContinueDialogAsync(cancellationToken);
            if (results.Status == DialogTurnStatus.Empty)
            {
                await dialogContext.BeginDialogAsync(dialog.Id, null, cancellationToken);
            }
         }
    }


我是机器人新手,也许我错了,但在我看来,问题在于消息属性“ChannelData”。回发键仅在emulator中可用,因此它不会通过团队拦截。我已经通过emulator连接到我的Azure机器人,它工作得非常好。告诉我如何通过团队正确使用卡片,这个问题有什么解决方案吗?

你的问题来源于我在一月份写回的答案,当时我已经编辑了这个答案,但有些人仍然偶尔无意中使用。我一直在玩“打鼹鼠”游戏,试图把它编辑成不存在的版本

您的
OnTurnAsync
方法很好。您应该从
Run
中删除此代码块,因为它1)基本上尝试做与
OnTurnAsync
相同的事情,2)最好将该功能保留在
OnTurnAsync
下(就像您已经做过的那样):

if(dialogContext.Context.Activity.GetType().GetProperty(“ChannelData”)!=null)
{
var channelData=JObject.Parse(dialogContext.Context.Activity.channelData.ToString());
if(channelData.ContainsKey(“回发”))
{
var postbackActivity=dialogContext.Context.Activity;
//将用户的自适应卡输入转换为文本提示输入
//必须作为字符串发送
postbackActivity.Text=postbackActivity.Value.ToString();
等待dialogContext.Context.SendActivityAsync(postbackActivity);
}
}

基本上,这失败的原因是Emulator将卡输入作为“回发”发送,但其他通道不这样做。但是,所有通道将其发送到
Activity.Value
,而将
Activity.Text
保留为空,因此
OnTurnAsync
中的代码是空的。它之所以会出现提示,可能是因为在
运行
中,您告诉它发送一条消息(
等待dialogContext.Context.SendActivityAsync(postbackActivity);
),这会打乱对话框的流程

有关其他上下文,请参阅


最后,我修改了Teams频道的DialogExtensions.cs,并从OnTurnAsync方法中删除了所有代码。当我们从卡中发送post数据时,如前一个示例中所示,我们试图捕获“postback”属性,该属性仅存在于emulator中。但在团队中,channelData只包含我们对话的id和带有我们活动类型的“源”键。仅当我们尝试从自适应卡提交数据时,此密钥才存在。更改后,我可以使用emulator中字符串类型的卡中的值:

   namespace Microsoft.BotBuilderSamples
{
    public static class DialogExtensions
    {
        public static async Task Run(this Dialog dialog, ITurnContext turnContext, IStatePropertyAccessor<DialogState> accessor, CancellationToken cancellationToken = default(CancellationToken))
        {

            var dialogSet = new DialogSet(accessor);
            dialogSet.Add(dialog);


            var dialogContext = await dialogSet.CreateContextAsync(turnContext, cancellationToken);


            if (dialogContext.Context.Activity.GetType().GetProperty("ChannelData") != null)
            {
                var channelData = JObject.Parse(dialogContext.Context.Activity.ChannelData.ToString());
                 //Check property in teams channel
                if (channelData.ContainsKey("source"))
                {
                    var postbackActivity = dialogContext.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();


                }
            }
            var results = await dialogContext.ContinueDialogAsync(cancellationToken);
            if (results.Status == DialogTurnStatus.Empty)
            {
                await dialogContext.BeginDialogAsync(dialog.Id, null, cancellationToken);
            }
名称空间Microsoft.BotBuilderSamples
{
公共静态类对话框扩展
{
公共静态异步任务运行(此对话框,iTunesContext turnContext,IStatePropertyAccessor访问器,CancellationToken CancellationToken=default(CancellationToken))
{
var dialogSet=新的dialogSet(访问器);
添加(对话框);
var dialogContext=await dialogSet.CreateContextAsync(turnContext,cancellationToken);
if(dialogContext.Context.Activity.GetType().GetProperty(“ChannelData”)!=null)
{
var channelData=JObject.Parse(dialogContext.Context.Activity.channelData.ToString());
//检查团队频道中的属性
if(channelData.ContainsKey(“源”))
{
var postbackActivity=dialogContext.Context.Activity;
//将用户的自适应卡输入转换为文本提示输入
//必须作为字符串发送
postbackActivity.Text=postbackActivity.Value.ToString();
}
}
var results=await dialogContext.ContinueDialogAsync(cancellationToken);
if(results.Status==DialogTurnStatus.Empty)
{
wait dialogContext.BeginDialogAsync(dialog.Id,null,cancellationToken);
}

我知道在这种情况下,这不是一个明确的解决方案。但我设法使自适应卡仅以这种方式在MS团队中工作。

谢谢你mdrichardson。我尝试过你的解决方案,但对我没有帮助。我用另一种方式解决了我的问题。我不知道是否是正确的解决方案,但它有效。我发现,当我们按submit按钮,“channeldata”属性有一个键“source”,该键具有我们活动的类型。我已将“postback”修改为该值,并将输入转换为字符串(postbackActivity.value.ToString();)没有继续对话。它在团队中工作得很好。当我们的机器人在不同的渠道中工作时,这个解决方案可能不好,但这不是我的情况。如果它在团队中工作,并且这是您计划使用的唯一渠道,那么我会坚持使用它。如果您将使用其他渠道,我会推荐更多类似于
If的内容(string.IsNullOrWhiteSpace(activity.Text)&&activity.Value!=null)
   namespace Microsoft.BotBuilderSamples
{
    public static class DialogExtensions
    {
        public static async Task Run(this Dialog dialog, ITurnContext turnContext, IStatePropertyAccessor<DialogState> accessor, CancellationToken cancellationToken = default(CancellationToken))
        {

            var dialogSet = new DialogSet(accessor);
            dialogSet.Add(dialog);


            var dialogContext = await dialogSet.CreateContextAsync(turnContext, cancellationToken);


            if (dialogContext.Context.Activity.GetType().GetProperty("ChannelData") != null)
            {
                var channelData = JObject.Parse(dialogContext.Context.Activity.ChannelData.ToString());
                 //Check property in teams channel
                if (channelData.ContainsKey("source"))
                {
                    var postbackActivity = dialogContext.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();


                }
            }
            var results = await dialogContext.ContinueDialogAsync(cancellationToken);
            if (results.Status == DialogTurnStatus.Empty)
            {
                await dialogContext.BeginDialogAsync(dialog.Id, null, cancellationToken);
            }