This can absolutely be done. I'm fairly certain I understand what you're looking for. If not, let me know and I'll edit this answer.
Create the Hero Cards
The important part is making sure that:
- The card has a button
- The button has a
CardAction
with an ImBack
action type and the appropriate value
var heroCard1 = new HeroCard
{
Title = "Option1",
Subtitle = "subtitle",
Text = "Some text",
Images = new List<CardImage> { new CardImage("https://sec.ch9.ms/ch9/7ff5/e07cfef0-aa3b-40bb-9baa-7c9ef8ff7ff5/buildreactionbotframework_960.jpg") },
Buttons = new List<CardAction> { new CardAction(ActionTypes.ImBack, "Option1", value: "Option1") },
};
var heroCard2 = new HeroCard
{
Title = "Option2",
Subtitle = "subtitle",
Text = "Some text",
Images = new List<CardImage> { new CardImage("https://sec.ch9.ms/ch9/7ff5/e07cfef0-aa3b-40bb-9baa-7c9ef8ff7ff5/buildreactionbotframework_960.jpg") },
Buttons = new List<CardAction> { new CardAction(ActionTypes.ImBack, "Option2", value: "Option2") },
};
var heroCard3 = new HeroCard
{
Title = "Option3",
Subtitle = "subtitle",
Text = "Some text",
Images = new List<CardImage> { new CardImage("https://sec.ch9.ms/ch9/7ff5/e07cfef0-aa3b-40bb-9baa-7c9ef8ff7ff5/buildreactionbotframework_960.jpg") },
Buttons = new List<CardAction> { new CardAction(ActionTypes.ImBack, "Option3", value: "Option3") },
};
Add the Hero Cards to a Message
var reply = stepContext.Context.Activity.CreateReply();
reply.AttachmentLayout = AttachmentLayoutTypes.Carousel;
reply.Attachments.Add(heroCard1.ToAttachment());
reply.Attachments.Add(heroCard2.ToAttachment());
reply.Attachments.Add(heroCard3.ToAttachment());
Send the Message, Followed By a Blank Text Prompt
Cards of any kind, by default, do not wait for user input. The blank text prompt is used force a wait and to capture the user's input, sending it to the next step.
await stepContext.Context.SendActivityAsync(reply);
return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions() { Prompt = MessageFactory.Text("") });
Result
Notes
I recommend using Hero Cards for this because:
- You can dynamically program the Hero Card however you want
- If you use an Adaptive Card, capturing input is a bit trickier
- If the input is just buttons, an Adaptive Card is overkill
- As @KyleDelaney mentioned, Adaptive Cards aren't supported on all channels
You can have any number of buttons per card and it will still work. The Result
is linked to the CardAction.value
Per @MattStannett
If you want to pass through a complex object rather than a simple string, this can be achieved by using the PostBack
action and JsonConvert.SerializeObject
to turn the object into a string. Using PostBack
means that the message won't be displayed in the chat, the result can be retrieved from the Result
object then read out using JsonConvert.DeserializeObject<>