Share via


Add rich card attachments to messages the v3 C# SDK

APPLIES TO: SDK v3

A message exchange between user and bot can contain one or more rich cards rendered as a list or carousel.

The Attachments property of the Activity object contains an array of Attachment objects that represent the rich cards and media attachments within the message.

Note

For information about how to add media attachments to messages, see Add media attachments to messages.

Types of rich cards

The Bot Framework currently supports eight types of rich cards:

Card type Description
Adaptive Card A customizable card that can contain any combination of text, speech, images, buttons, and input fields. See per-channel support.
Animation Card A card that can play animated GIFs or short videos.
Audio Card A card that can play an audio file.
Hero Card A card that typically contains a single large image, one or more buttons, and text.
Thumbnail Card A card that typically contains a single thumbnail image, one or more buttons, and text.
Receipt Card A card that enables a bot to provide a receipt to the user. It typically contains the list of items to include on the receipt, tax and total information, and other text.
SignIn Card A card that enables a bot to request that a user sign-in. It typically contains text and one or more buttons that the user can click to initiate the sign-in process.
Video Card A card that can play videos.

Tip

To display multiple rich cards in list format, set the activity's AttachmentLayout property to "list". To display multiple rich cards in carousel format, set the activity's AttachmentLayout property to "carousel". If the channel does not support carousel format, it will display the rich cards in list format, even if the AttachmentLayout property specifies "carousel".

Process events within rich cards

To process events within rich cards, define CardAction objects to specify what should happen when the user clicks a button or taps a section of the card. Each CardAction object contains these properties:

Property Type Description
Type string type of action (one of the values specified in the table below)
Title string title of the button
Image string image URL for the button
Value string value needed to perform the specified type of action

Note

Buttons within Adaptive Cards are not created using CardAction objects, but instead using the schema that is defined by Adaptive Cards. See Add an Adaptive Card to a message for an example that shows how to add buttons to an Adaptive Card.

This table lists the valid values for CardAction.Type and describes the expected contents of CardAction.Value for each type:

CardAction.Type CardAction.Value
openUrl URL to be opened in the built-in browser
imBack Text of the message to send to the bot (from the user who clicked the button or tapped the card). This message (from user to bot) will be visible to all conversation participants via the client application that is hosting the conversation.
postBack Text of the message to send to the bot (from the user who clicked the button or tapped the card). Some client applications may display this text in the message feed, where it will be visible to all conversation participants.
call Destination for a phone call in this format: 123123123123
playAudio URL of audio to be played
playVideo URL of video to be played
showImage URL of image to be displayed
downloadFile URL of file to be downloaded
signin URL of OAuth flow to be initiated

Add a Hero card to a message

The Hero card typically contains a single large image, one or more buttons, and text.

This code example shows how to create a reply message that contains three Hero cards rendered in carousel format:

Activity replyToConversation = message.CreateReply("Should go to conversation, in carousel format");
replyToConversation.AttachmentLayout = AttachmentLayoutTypes.Carousel;
replyToConversation.Attachments = new List<Attachment>();

Dictionary<string, string> cardContentList = new Dictionary<string, string>();
cardContentList.Add("PigLatin", "https://<ImageUrl1>");
cardContentList.Add("Pork Shoulder", "https://<ImageUrl2>");
cardContentList.Add("Bacon", "https://<ImageUrl3>");

foreach(KeyValuePair<string, string> cardContent in cardContentList)
{
    List<CardImage> cardImages = new List<CardImage>();
    cardImages.Add(new CardImage(url:cardContent.Value ));

    List<CardAction> cardButtons = new List<CardAction>();

    CardAction plButton = new CardAction()
    {
        Value = $"https://en.wikipedia.org/wiki/{cardContent.Key}",
        Type = "openUrl",
        Title = "WikiPedia Page"
    };

    cardButtons.Add(plButton);

    HeroCard plCard = new HeroCard()
    {
        Title = $"I'm a hero card about {cardContent.Key}",
        Subtitle = $"{cardContent.Key} Wikipedia Page",
        Images = cardImages,
        Buttons = cardButtons
    };

    Attachment plAttachment = plCard.ToAttachment();
    replyToConversation.Attachments.Add(plAttachment);
}

var reply = await connector.Conversations.SendToConversationAsync(replyToConversation);

Add a Thumbnail card to a message

The Thumbnail card typically contains a single thumbnail image, one or more buttons, and text.

This code example shows how to create a reply message that contains two Thumbnail cards rendered in list format:

Activity replyToConversation = message.CreateReply("Should go to conversation, in list format");
replyToConversation.AttachmentLayout = AttachmentLayoutTypes.List;
replyToConversation.Attachments = new List<Attachment>();

Dictionary<string, string> cardContentList = new Dictionary<string, string>();
cardContentList.Add("PigLatin", "https://<ImageUrl1>");
cardContentList.Add("Pork Shoulder", "https://<ImageUrl2>");

foreach(KeyValuePair<string, string> cardContent in cardContentList)
{
    List<CardImage> cardImages = new List<CardImage>();
    cardImages.Add(new CardImage(url:cardContent.Value ));

    List<CardAction> cardButtons = new List<CardAction>();

    CardAction plButton = new CardAction()
    {
        Value = $"https://en.wikipedia.org/wiki/{cardContent.Key}",
        Type = "openUrl",
        Title = "WikiPedia Page"
    };

    cardButtons.Add(plButton);

    ThumbnailCard plCard = new ThumbnailCard()
    {
        Title = $"I'm a thumbnail card about {cardContent.Key}",
        Subtitle = $"{cardContent.Key} Wikipedia Page",
        Images = cardImages,
        Buttons = cardButtons
    };

    Attachment plAttachment = plCard.ToAttachment();
    replyToConversation.Attachments.Add(plAttachment);
}

var reply = await connector.Conversations.SendToConversationAsync(replyToConversation);

Add a Receipt card to a message

The Receipt card enables a bot to provide a receipt to the user. It typically contains the list of items to include on the receipt, tax and total information, and other text.

This code example shows how to create a reply message that contains a Receipt card:

Activity replyToConversation = message.CreateReply("Should go to conversation");
replyToConversation.Attachments = new List<Attachment>();

List<CardImage> cardImages = new List<CardImage>();
cardImages.Add(new CardImage(url: "https://<imageUrl1>" ));

List<CardAction> cardButtons = new List<CardAction>();

CardAction plButton = new CardAction()
{
    Value = $"https://en.wikipedia.org/wiki/PigLatin",
    Type = "openUrl",
    Title = "WikiPedia Page"
};

cardButtons.Add(plButton);

ReceiptItem lineItem1 = new ReceiptItem()
{
    Title = "Pork Shoulder",
    Subtitle = "8 lbs",
    Text = null,
    Image = new CardImage(url: "https://<ImageUrl1>"),
    Price = "16.25",
    Quantity = "1",
    Tap = null
};

ReceiptItem lineItem2 = new ReceiptItem()
{
Title = "Bacon",
Subtitle = "5 lbs",
Text = null,
Image = new CardImage(url: "https://<ImageUrl2>"),
Price = "34.50",
Quantity = "2",
Tap = null
};

List<ReceiptItem> receiptList = new List<ReceiptItem>();
receiptList.Add(lineItem1);
receiptList.Add(lineItem2);

ReceiptCard plCard = new ReceiptCard()
{
    Title = "I'm a receipt card, isn't this bacon expensive?",
    Buttons = cardButtons,
    Items = receiptList,
    Total = "112.77",
    Tax = "27.52"
};

Attachment plAttachment = plCard.ToAttachment();
replyToConversation.Attachments.Add(plAttachment);

var reply = await connector.Conversations.SendToConversationAsync(replyToConversation);

Add a Sign-in card to a message

The Sign-in card enables a bot to request that a user sign-in. It typically contains text and one or more buttons that the user can click to initiate the sign-in process.

This code example shows how to create a reply message that contains a Sign-in card:

Activity replyToConversation = message.CreateReply("Should go to conversation");
replyToConversation.Attachments = new List<Attachment>();

List<CardAction> cardButtons = new List<CardAction>();

CardAction plButton = new CardAction()
{
    Value = $"https://<OAuthSignInURL",
    Type = "signin",
    Title = "Connect"
};

cardButtons.Add(plButton);

SigninCard plCard = new SigninCard(title: "You need to authorize me", button: plButton);

Attachment plAttachment = plCard.ToAttachment();
replyToConversation.Attachments.Add(plAttachment);

var reply = await connector.Conversations.SendToConversationAsync(replyToConversation);

Add an Adaptive card to a message

The Adaptive Card can contain any combination of text, speech, images, buttons, and input fields. Adaptive Cards are created using the JSON format specified in Adaptive Cards, which gives you full control over card content and format.

To create an Adaptive Card using .NET, install the AdaptiveCards NuGet package. Then, leverage the information within the Adaptive Cards site to understand Adaptive Card schema, explore Adaptive Card elements, and see JSON samples that can be used to create cards of varying composition and complexity. Additionally, you can use the Interactive Visualizer to design Adaptive Card payloads and preview card output.

This code example shows how to create a message that contains an Adaptive Card for a calendar reminder:

Activity replyToConversation = message.CreateReply("Should go to conversation");
replyToConversation.Attachments = new List<Attachment>();

AdaptiveCard card = new AdaptiveCard();

// Specify speech for the card.
card.Speak = "<s>Your  meeting about \"Adaptive Card design session\"<break strength='weak'/> is starting at 12:30pm</s><s>Do you want to snooze <break strength='weak'/> or do you want to send a late notification to the attendees?</s>";

// Add text to the card.
card.Body.Add(new TextBlock()
{
    Text = "Adaptive Card design session",
    Size = TextSize.Large,
    Weight = TextWeight.Bolder
});

// Add text to the card.
card.Body.Add(new TextBlock()
{
    Text = "Conf Room 112/3377 (10)"
});

// Add text to the card.
card.Body.Add(new TextBlock()
{
    Text = "12:30 PM - 1:30 PM"
});

// Add list of choices to the card.
card.Body.Add(new ChoiceSet()
{
    Id = "snooze",
    Style = ChoiceInputStyle.Compact,
    Choices = new List<Choice>()
    {
        new Choice() { Title = "5 minutes", Value = "5", IsSelected = true },
        new Choice() { Title = "15 minutes", Value = "15" },
        new Choice() { Title = "30 minutes", Value = "30" }
    }
});

// Add buttons to the card.
card.Actions.Add(new OpenUrlAction()
{
    Url = "http://foo.com",
    Title = "Snooze"
});

card.Actions.Add(new OpenUrlAction()
{
    Url = "http://foo.com",
    Title = "I'll be late"
});

card.Actions.Add(new OpenUrlAction()
{
    Url = "http://foo.com",
    Title = "Dismiss"
});

// Create the attachment.
Attachment attachment = new Attachment()
{
    ContentType = AdaptiveCard.ContentType,
    Content = card
};

replyToConversation.Attachments.Add(attachment);

var reply = await connector.Conversations.SendToConversationAsync(replyToConversation);

The resulting card contains three blocks of text, an input field (choice list), and three buttons:

Adaptive Card calendar reminder

Additional resources