Botframework V4:有关输入表单卡的问题

2024-01-26

你好,我有这张输入表格卡。它渲染正确,但我怎样才能得到它的结果?我怎样才能让机器人等待用户提交然后再继续下一步?放入stepContext.NextAsync将自动触发下一步。但是删除它会导致错误,因为它需要返回一些东西。

   public InitialQuestions(string dialogId, IEnumerable<WaterfallStep> steps = null)
        : base(dialogId, steps)
    {
        AddStep(async (stepContext, cancellationToken) =>
        {
            var cardAttachment = CreateAdaptiveCardAttachment(_cards);
            var reply = stepContext.Context.Activity.CreateReply();
            reply.Attachments = new List<Attachment>() { cardAttachment };
            await stepContext.Context.SendActivityAsync(reply, cancellationToken);

            // how can i wait for user to click submit before going to next step?
            return await stepContext.NextAsync();

            // return await stepContext.PromptAsync(
            //   "textPrompt",
            //   new PromptOptions
            //   {
            //       Prompt = MessageFactory.Text(""),
            //   },
            //   cancellationToken: cancellationToken);

        });

        AddStep(async (stepContext, cancellationToken) =>
        {
            // next step
        });
    }

     private static Attachment CreateAdaptiveCardAttachment(string filePath)
    {
        var adaptiveCardJson = File.ReadAllText(filePath);
        var adaptiveCardAttachment = new Attachment()
        {
            ContentType = "application/vnd.microsoft.card.adaptive",
            Content = JsonConvert.DeserializeObject(adaptiveCardJson),
        };
        return adaptiveCardAttachment;
    }

这是卡

{
  "type": "AdaptiveCard",
  "body": [
    {
      "type": "TextBlock",
      "text": "What is your Occupation?"
    },
    {
      "type": "Input.Text",
      "id": "Occupation",
      "placeholder": "Occupation"
    },
    {
      "type": "TextBlock",
      "text": "Are you married? "
    },
    {
      "type": "Input.ChoiceSet",
      "id": "Married",
      "value": "true",
      "choices": [
        {
          "title": "Yes",
          "value": "true"
        },
        {
          "title": "No",
          "value": "false"
        }
      ],
      "style": "expanded"
    },
    {
      "type": "TextBlock",
      "text": "When is your birthday?"
    },
    {
      "type": "Input.Date",
      "id": "Birthday",
      "value": ""
    }
  ],
  "actions": [
    {
      "type": "Action.Submit",
      "title": "Submit",
      "data": {
        "id": "1234567890"
      }
    }
  ],
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.0"
}

多谢你们。

编辑:为了供其他人将来参考,这是我找到的答案。

    AddStep(async (stepContext, cancellationToken) =>
    {
        var state = await (stepContext.Context.TurnState["BasicAccessors"] as BasicAccessors).BasicStateAccessor.GetAsync(stepContext.Context);

        var jsonString = (JObject)stepContext.Context.Activity.Value;
        BasicState results = JsonConvert.DeserializeObject<BasicState>(jsonString.ToString());
        state.Occupation = results.Occupation;
        state.Married = results.Married;
        state.Birthday = results.Birthday;

        return await stepContext.NextAsync();
    });

让我以相反的顺序回答你的问题:

我怎样才能让机器人等待用户提交然后再继续下一步?放入stepContext.NextAsync将自动触发下一步。但是删除它会导致错误,因为它需要返回一些东西。

是的,确实如此,您需要从步骤中返回一些内容,但正如您所指出的,您还没有准备好进入下一步。答案是此时您想使用提示!现在我看到你在这里注释掉了一些代码来执行此操作,也许令人困惑的是,今天没有关于使用卡片的具体提示。相反,您确实想使用通用目的TextPrompt我们会将其上的活动设置为除简单文本之外的其他内容。

考虑到这一点,您将保留上面使用的代码CreateReply建立你的Activity带有卡片附件,但是,而不是发送它Activity你自己与SendActivityAsync你想将其设置为Prompt的财产TextPrompt像这样:

AddStep(async (stepContext, cancellationToken) =>
        {
            return await stepContext.PromptAsync(
               "myPrompt",
               new PromptOptions
               {
                   Prompt = new Activity 
                   {
                       Type = ActivityTypes.Message,
                       Attachments = new List<Attachment>() 
                       { 
                          CreateAdaptiveCardAttachment(_cards),
                       },
                   },
               },
               cancellationToken: cancellationToken);

        });

好的,这就是问题的一半。现在考虑到这一点,让我们回到问题的第一部分:

你好,我有这张输入表格卡。它渲染正确,但我怎样才能得到它的结果?

那么,您的自适应卡正在使用Submit操作,这意味着您将收到一个包含表单值的活动Values的财产Activity,但是因为我们使用了TextPrompt高于默认的验证行为TextPrompt将验证是否为Text的一部分Activity在这种情况下不会有。因此,要解决这个问题,当您配置TextPrompt你确实想提供自己的PromptValidator<T>像这样:

    Add(new TextPrompt("myPrompt", new PromptValidator<string>(async (pvc, ct) => true)));

这基本上表明输入无论如何都是有效的。如果您愿意,可以通过实际检查该值的详细信息来使其更丰富,但这现在应该可以解除您的障碍。

现在,回到你的WaterfallDialog您的下一步将是收到Activity whose Value财产将是一个JObject您可以直接使用,也可以调用JObject::ToObject<T>将其转换为您创建的代表表单输入的特定类:

AddStep(async (stepContext, cancellationToken) =>
        {
           // This will give you a JObject representation of the incoming values 
           var rawValues = (JObject)stepContext.Context.Activity.Values;

           // You can convert that to something more strongly typed like so
           // where MyFormValues is a class you've defined
           var myFormValues = rawValues.ToObject<MyFormValues>();
        });

我想在结束这个答案时说,在回答你的问题时,我记录了一堆反馈,我打算将这些反馈发送给产品团队,以在 API 设计和文档方面改善这种情况,因为很明显,这并不明显或最优。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Botframework V4:有关输入表单卡的问题 的相关文章

随机推荐