Botframework V4:有关输入表单卡的问题 [英] Botframework V4: Question about Input forms cards
问题描述
你好,我有这张输入表格卡.它可以正确渲染,但是我如何获得结果呢?以及如何使机器人在继续下一步之前等待用户提交?放置stepContext.NextAsync将自动触发下一步.但是删除它会导致错误,因为它需要返回一些东西.
Hello i have this input forms card. It is rendering properly but how can i get its results? And how can i make it so that the bot wait for the user to submit before proceding to the next step? Putting stepContext.NextAsync will automatically trigger the next step. But removing it will cause an error because it needs to return something.
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"
}
谢谢大家.
这是我找到的答案,供其他参考,以供将来参考.
for future reference of others this is the answer i found.
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();
});
推荐答案
让我以相反的顺序回答您的问题:
Let me answer your questions in reverse order:
我该怎么做,以便机器人在继续下一步之前等待用户提交?放置stepContext.NextAsync将自动触发下一步.但是删除它会导致错误,因为它需要返回一些东西.
And how can i make it so that the bot wait for the user to submit before proceding to the next step? Putting stepContext.NextAsync will automatically trigger the next step. But removing it will cause an error because it needs to return something.
是的,的确是这样,您需要从步骤中返回一些内容,但是正如您指出的那样,您还没有准备好将其移至下一步.答案是您要在此时使用提示!现在,我看到您在此处已注释掉一些代码来执行此操作,也许令人困惑的是,今天,没有使用卡的特定提示.相反,您确实想使用通用的TextPrompt
,我们将在其上将活动设置为除简单文本之外的其他内容.
Yes, it's true, you need to return something from your step, but as you point out you're not ready for it to move to the next step yet. The answer is that you want to use a prompt at this point! Now I see you have some code in here commented out to do this and maybe what's confusing is that, today, there is no specific prompt for working with cards. Instead you do want to use a general purpose TextPrompt
and we'll set the activity on that to something other than just simple text.
请牢记这一点,您可以将代码保持在使用CreateReply
来构建带有卡片附件的Activity
的代码之上,但是,您不想将其与SendActivityAsync
一起发送给自己,而是将其设置为TextPrompt
的Prompt
属性的值,如下所示:
With this in mind, you would keep your code above that is using CreateReply
to build your Activity
with card attachments, but, instead of sending that Activity
yourself with SendActivityAsync
you want to set it as the value of the Prompt
property of the TextPrompt
like so:
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);
});
好的,这就是问题的一半.现在考虑到这一点,让我们回到问题的第一部分:
Ok, so that's one half of the problem. With that in mind now, let's circle back to the first part of your question:
你好,我有这张输入表格卡.它可以正确渲染,但是我如何获得结果呢?
Hello i have this input forms card. It is rendering properly but how can i get its results?
好吧,您的自适应卡正在使用Submit
操作,这意味着您将收到一个活动,其中包含Activity
的Values
属性中表格的值,但是,因为我们使用了TextPrompt
高于TextPrompt
的默认验证行为的操作将验证是否为Activity
的Text
部分提供了一些值,在这种情况下不会提供.因此,要解决此问题,在配置TextPrompt
时,您确实想像这样提供自己的PromptValidator<T>
:
Well, your adaptive card is using the Submit
action which means that you will receive an activity that contains the values of the form in the Values
property of the Activity
, however because we used a TextPrompt
above the default validation behavior of the TextPrompt
is going to be validating that some value was supplied for the Text
portion of the Activity
which there won't be in this case. So, to fix that, when you configure the TextPrompt
you really want to provide your own PromptValidator<T>
like so:
Add(new TextPrompt("myPrompt", new PromptValidator<string>(async (pvc, ct) => true)));
这基本上表明输入无论如何都是有效的.如果需要,可以通过实际检查值的详细信息来使其更丰富,但这现在应该解除对您的限制.
This basically says the input is valid no matter what. You could make it richer if you wanted by actually checking the details of the value, but this should unblock you for now.
现在,回到您的WaterfallDialog
中,下一步将是接收Activity
,其Value
属性将是JObject
,您可以直接使用它,也可以调用JObject::ToObject<T>
进行转换进入您创建的代表表单输入的特定类:
Now, back in your WaterfallDialog
your next step is going to be receiving the Activity
whose Value
property will be a JObject
which you can either use directly or you can call JObject::ToObject<T>
to convert it into a specific class you've created that represents your form input:
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设计和文档方面的情况,因为,显然,这不是显而易见的还是最优的.
I want to just close this answer out by saying that, in answering your question, I've recorded a bunch of feedback that I intend to send to the product team to improve this situation both in terms of API design and documentation because, clearly, this is not obvious or optimal.
这篇关于Botframework V4:有关输入表单卡的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!