By far, the most common issue that the Support Team answers is along the lines of, "How do I capture input from Adaptive Cards with my bot?" There are no official samples or documentation to show a user how to accomplish this. Therefore, the workaround to make this work is difficult to intuit or discover.
There are two different approaches we can take towards making this easier for our customers:
- Provide samples and documentation that show how to accomplish this
- Provide an AdaptiveCardPrompt that makes this easy to implement
Many of our customers use Adaptive Cards to gather user input. This is likely preferred by many of our customers to using multi-turn interactions with their bots to gather user information because it is more efficient and provides a better user experience.
Because Adaptive Card input is sent through Activity.Value
and not Activity.Text
, it will not show up in a Waterfall Dialog's StepContext.Result
. This makes it difficult for many users to use Adaptive Cards to gather user data; they don't know the "correct" way to accomplish this in their bots.
Since this is both a popular desire for our customers and we don't provide anything official that either makes this easy or shows them how to do it, this is the most common issue that our Support Team receives.
Similarly the Support Team frequently sees the following Adaptive Card features requested:
- Ability to require certain input fields
- Ensure that the bot only responds to input from specific Adaptive Cards if there are many displayed in the chat window and the user responds with the "wrong" one
When presented with these customer issues, our current recommendation is generally to:
- Send the adaptive card as an attachment to a blank text prompt
- In
OnTurn
, copyActivity.Value
toActivity.Text
. In C#, this gets a little more difficult and "hacky" due to needing null coalescence checks and JSON serialization
The "easiest" solution would be to simply provide documentation on how to do this and/or a sample that uses ActivityPrompt
, which returns the entire context.Activity
as the StepContext.Result
.
- Little and relatively simple extra code to support
- The documentation or sample will also show how to address similar issues that may be solved with
ActivityPrompt
- The solution doesn't directly address the problem
- Does not add other frequently-requested features related to Adaptive Cards
- We have a related Blog Post, but that doesn't seem to have decreased the rate we see this issue
We could provide an AdaptiveCardPrompt that solves this issue in a very user-friendly way by simply having the user include the Adaptive Card in the AdaptiveCardPrompt's Prompt
property, or passed into it's constructor.
I have created this as PR for both the C# and Node SDKs along with:
- Unit tests for both SDKs
- Samples of usage in Experimental Samples for both SDKs
It also includes the following key features frequently requested by customers:
- Card can be passed in constructor or as prompt/reprompt activity attachment
- Includes validation for specified required input fields
- Displays custom message if user replies via text and not card input
- Ensures input is only valid if it comes from the appropriate card (not one shown previous to prompt)
- Very easy for developers to gather user input using Adaptive Cards
- Provides many frequently-requested features that would take significant work for a developer to implement themselves
- Adds additional, complex code for the SDK to support and maintain
- Would still benefit from official Samples and Documentation
private static async Task<DialogTurnResult> ShowCardAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
// STANDARD FOR ADAPTIVE CARD USE
var cardPath = Path.Combine("../Resources/", "adaptiveCard.json");
var cardJson = File.ReadAllText(cardPath);
var cardAttachment = new Attachment()
{
ContentType = "application/vnd.microsoft.card.adaptive",
Content = JsonConvert.DeserializeObject(cardJson),
};
// END STANDARD FOR ADAPTIVE CARD USE
// SPECIFIC TO ADAPTIVECARDPROMPT
// Adaptive Card can be either passed in `AdaptiveCardPromptSettings`...
var promptSettings = new AdaptiveCardPromptSettings()
{
Card = cardAttachment
};
// ...or directly to the prompt's `PromptOptions.Prompt`
return await stepContext.PromptAsync(nameof(AdaptiveCardPrompt), new PromptOptions()
{
Prompt = new Activity { Attachments = new List<Attachment>() { cardAttachment } }
});
}
private async Task<DialogTurnResult> DisplayResultsAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
// Use the result
var result = stepContext.Result as JObject;
// Do something with `result`
}
- DCR/Issue
- AdaptiveCardPrompt: C# / Node
- Experimental Samples:
- Note: C# Sample doesn't currently "work" because it uses (both are marked
internal
andAdaptiveCardPrompt
hasn't been merged into the SDK):
- Note: C# Sample doesn't currently "work" because it uses (both are marked
- Related Support Team Issues
- The many times Michael Richardson has answered on StackOverflow
- The many times Kyle Delaney has answered on StackOverflow