Search code examples
jsonbotframework

Bind data in Adaptive cards in Bot framework


How can we bind data to the adaptive cards from backend ? I have designed a card from https://adaptivecards.io/designer which returns a JSON file.


Solution

  • AdaptiveCards are essentially just JSON Objects, so adding your content to it is as simple as editing the JSON created with the AdaptiveCard Designer. In NodeJs this is pretty simple; however, in C# you need to use JObject and JArray to parse and modify the JSON file from the designer.

    Adaptive Card

    Here is a simple AdaptiveCard I created with the designer that I will use in my examples for NodeJs and C# below.

    {
        "type": "AdaptiveCard",
        "body": [
            {
                "type": "TextBlock",
                "horizontalAlignment": "Center",
                "weight": "Bolder",
                "text": "My Adaptive Card",
                "isSubtle": true
            },
            {
                "type": "TextBlock",
                "text": "New TextBlock"
            }
        ],
        "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
        "version": "1.0"
    }
    

    NodeJS BotFramework SDK V4

    Once we read the AdaptiveCard in from the JSON file, we can directly change the values in the card or add additional components. Then we can use the CardFactory to render the card and send it to the user.

    const { CardFactory } = require('botbuilder');
    const Card = require('./resources/my-adaptive-card');
    
    ...
    
    // Change Text Field
    Card.body[1].text = "Item 1";
    
    // Add Text Field
    Card.body.push({
        type: "TextBlock",
        text: "Item 2"
    });
    
    await turnContext.sendActivity({attachments: [CardFactory.adaptiveCard(Card)]});
    

    C# BotFramework SDK V4

    Since we can't directly modify JSON in C# as we can in NodeJS, we have to use the Newtonsoft.Json.Linq namespace so we can make changes to the card with JObject and JArray. Once we've made the necessary changes, the card can be rendered and sent to the user as an AdaptiveCard.

    For more information on modifying JSON in C#, check out the JSON.Net Documentation.

    using Newtonsoft.Json.Linq;
    
    ...
    
    // Parse AdaptiveCard JSON from file
    var adaptiveCardJson = File.ReadAllText(@".\Resources\AdaptiveCard.json");
    JObject json = JObject.Parse(adaptiveCardJson);
    
    // Get the `body` of the AdaptiveCard
    JArray body = (JArray)json["body"];
    
    // Change Text Field
    ((JObject)body[1])["text"] = "Item 1";
    
    // Add Text Field
    body.Add(JObject.Parse("{\"type\": \"TextBlock\", \"text\": \"Item 2\"}"));
    
    var adaptiveCardAttachment = new Attachment()
    {
        ContentType = "application/vnd.microsoft.card.adaptive",
        Content = JsonConvert.DeserializeObject(json.ToString()),
    };
    
    var reply = turnContext.Activity.CreateReply();
    reply.Attachments = new List<Attachment>() { adaptiveCardAttachment };
    await turnContext.SendActivityAsync(reply, cancellationToken);
    

    Result

    AdaptiveCard before changes
    Adaptive Card before changes

    AdaptiveCard after changes
    AdaptiveCard after changes