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

时间:2019-01-20 12:25:28

标签: c# botframework adaptive-cards

你好,我有这张输入表格卡。它渲染正确,但是我如何获得结果呢?以及如何使机器人在继续下一步之前等待用户提交?放置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();
    });

1 个答案:

答案 0 :(得分:2)

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

  

我该怎么做,以便机器人在继续下一步之前等待用户提交?放置stepContext.NextAsync将自动触发下一步。但是删除它会导致错误,因为它需要返回一些东西。

是的,的确是这样,您需要从步骤中返回一些内容,但是正如您指出的那样,您还没有准备好将其移至下一步。答案是您现在要使用提示!现在,我看到您在此处注释了一些代码来执行此操作,也许令人困惑的是,今天,没有使用卡的特定提示。相反,您确实想使用通用的TextPrompt,并且我们将在其上将活动设置为除简单文本以外的其他内容。

考虑到这一点,您将使代码保持在使用CreateReply来构建带有卡片附件的Activity的代码之上,而不是自己通过{{1 }},您希望将其设置为Activity的{​​{1}}属性的值,如下所示:

SendActivityAsync

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

  

你好,我有这张输入表格卡。它可以正确渲染,但是我如何获得结果呢?

好吧,您的自适应卡正在使用Prompt操作,这意味着您将收到一个活动,其中包含TextPrompt的{​​{1}}属性中表格的值,但是,因为我们在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的{​​{1}}部分提供了一些值,而该值不会在这种情况下。因此,要解决此问题,在配置Activity时,您确实想像这样提供自己的TextPrompt

TextPrompt

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

现在,回到您的Text中,下一步将是接收Activity,其TextPrompt属性为PromptValidator<T>的{​​{1}}可以调用 Add(new TextPrompt("myPrompt", new PromptValidator<string>(async (pvc, ct) => true))); 将其转换为您创建的代表表单输入的特定类:

WaterfallDialog

在结束回答时,我想说,在回答您的问题时,我记录了很多反馈,我打算将这些反馈发送给产品团队以改善API设计和文档方面的情况,因为,显然,这不是显而易见的还是最优的。