C# Botframework V4:关于输入表单卡的问题

C# Botframework V4:关于输入表单卡的问题,c#,botframework,adaptive-cards,C#,Botframework,Adaptive Cards,你好,我有这张输入表格卡。它正在正确渲染,但如何获得其结果?我怎样才能使bot在继续下一步之前等待用户提交?放置stepContext.NextAsync将自动触发下一步。但是删除它会导致错误,因为它需要返回一些内容 public InitialQuestions(string dialogId, IEnumerable<WaterfallStep> steps = null) : base(dialogId, steps) { AddS

你好,我有这张输入表格卡。它正在正确渲染,但如何获得其结果?我怎样才能使bot在继续下一步之前等待用户提交?放置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;
    }
谢谢各位

编辑:这是我找到的答案,供以后参考

    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();
    });
AddStep(异步(stepContext,cancellationToken)=>
{
var state=await(stepContext.Context.TurnState[“BasicAccessors”]作为BasicAccessor)。BasicStateAccessor.GetAsync(stepContext.Context);
var jsonString=(JObject)stepContext.Context.Activity.Value;
BasicState results=JsonConvert.DeserializeObject(jsonString.ToString());
状态.职业=结果.职业;
州。已婚=结果。已婚;
state.birth=结果.birth;
返回wait-stepContext.NextAsync();
});

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

我怎样才能使bot在继续下一步之前等待用户提交?放置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;
    }
是的,这是真的,你需要从你的步骤中返回一些东西,但是正如你指出的,你还没有准备好让它进入下一步。答案是您希望在此时使用提示!现在我看到这里有一些代码被注释掉了,可能让人困惑的是,今天,没有关于使用卡片的具体提示。相反,您确实希望使用通用的
TextPrompt
,我们将在该提示符上设置活动,而不仅仅是简单的文本

记住这一点,您可以在上面保留代码,即使用
CreateReply
构建带有卡附件的
活动,但是,您希望将其设置为
TextPrompt
Prompt
属性的值,而不是使用
SendActivityAsync
自己发送该
活动,如下所示:

AddStep(异步(stepContext,cancellationToken)=>
{
return wait stepContext.PromptAsync(
“我的提示”,
新提示
{
Prompt=新活动
{
类型=ActivityTypes.Message,
附件=新列表()
{ 
创建AdaptiveCardAttachment(_卡),
},
},
},
cancellationToken:cancellationToken);
});
好的,这就是问题的一半。考虑到这一点,让我们回到问题的第一部分:

你好,我有这张输入表格卡。它正在正确渲染,但如何获得其结果

您的自适应卡正在使用
提交
操作,这意味着您将收到一个包含
活动
属性中表单值的活动,但是,由于我们在上面使用了
TextPrompt
,因此
TextPrompt
的默认验证行为将验证是否为
活动
Text
部分提供了某个值,而在本例中不会提供该值。因此,为了解决这个问题,当您配置
TextPrompt
时,您确实希望提供自己的
PromptValidator
,如下所示:

Add(newtextprompt(“myPrompt”),newpromptValidator(异步(pvc,ct)=>true));
这基本上意味着无论发生什么,输入都是有效的。如果您愿意,您可以通过实际检查值的详细信息来使其更丰富,但现在应该取消对您的阻止

现在,回到您的
waterwall对话框
中,您的下一步将接收
活动
,其
属性将是一个
作业对象
,您可以直接使用该属性,也可以调用
作业对象::ToObject
将其转换为您创建的表示表单输入的特定类:

AddStep(异步(stepContext,cancellationToken)=>
{
//这将为您提供传入值的JObject表示
var rawValues=(JObject)stepContext.Context.Activity.Values;
//您可以将其转换为类似这样的强类型
//其中MyFormValues是您定义的类
var myFormValues=rawValues.ToObject();
});

最后,我想说,在回答您的问题时,我记录了一系列反馈,我打算发送给产品团队,以改善API设计和文档方面的这种情况,因为很明显,这不是显而易见的或最佳的。

先生,“ToObject”中有一个错误这需要nuget软件包吗?我有一个名为“职业、生日、已婚”的类“BasicState”。很抱歉,我在回答的代码中留下了一个到
JObject
的演员阵容,现在正在更新。谢谢先生,抱歉,这是我第一次使用json。你能教我如何直接访问这些json值吗?简单的回答是,你可以像使用字典一样使用它来访问你需要的每个值,但我保证如果你搜索这个网站,关于如何使用
JObject
,会有很多问题/答案。我用drew爵士的答案编辑了我的问题。我的答案正确吗?还是为并发用户保存?