1

How to dynamically change my custom adaptive card's text property value from within my C# code?

Here is my C# code

public static Attachment CreateMySearchCardAttachment()
        {
            // combine path for cross platform support
            string[] paths = { ".", "Resources", "MySearchCard.json" };
            var MySearchCardJson = File.ReadAllText(Path.Combine(paths));

            var adaptiveCardAttachment = new Attachment()
            {
                ContentType = "application/vnd.microsoft.card.adaptive",
                Content = JsonConvert.DeserializeObject(MySearchCardJson),

            };

            return adaptiveCardAttachment;
        }

And my MySearchCard.json file goes below

{
  "type": "AdaptiveCard",
  "body": [
    {
      "type": "ColumnSet",
      "columns": [
        {
          "type": "Column",
          "items": [
            {
              "type": "Image",
              "horizontalAlignment": "Right",
              "spacing": "None",
              "url": "",
              "size": "Medium",
              "width": "2px",
              "height": "2px"
            },
            {
              "type": "TextBlock",
              "size": "Medium",
              "weight": "Bolder",
              "text": "Knowledgebase Search"
            },
            {
              "type": "Input.Text",
              "id": "searchText",
              "placeholder": "Type your search text and click Search"
            }
          ],
          "width": 2
        }
      ]
    }
  ],
  "actions": [
    {
      "type": "Action.Submit",
      "title": "Search"
    }
  ],
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.0"
}
I am able to get this adaptive card to display inside my chat bot.But not sure how to dynamically change the text labels or their values. We want to dynamically change some of the text labels before displaying, then after displaying,dynamically show or hide based on user response.At a later point we want to integrate chat BoT with MS Teams.But prior to that I need to show the same from my emulator

If you look at my json, there is a text property with "text": "Knowledgebase Search". My question is how to change this text value dynamically from within my C# code?

roney
  • 964
  • 3
  • 15
  • 37
  • Just to be sure: when do you want to change it from your code? Before sending the card from the bot to the user, or after it has been displayed (and in that case, for which channel)? – Nicolas R May 17 '19 at 08:33
  • @ Nicolas I want to change some of the text labels before displaying, then after displaying,dynamically show or hide based on user response.At a later point we want to integrate chat BoT with MS Teams.But prior to that I need to show the same from my emulator. – roney May 17 '19 at 13:37

1 Answers1

1

Dynamically Changing Before Being Displayed

There's a few different ways to do this. The first option is probably the best, but they should all work.

1. Use the AdaptiveCards Package

Note: This package is different from, and newer than, Microsoft.AdaptiveCards -- Don't use this one

Since you know the exact part of the card that you'd like to change, you can:

string[] paths = { ".", "AdaptiveCard.json" };
var cardJson = File.ReadAllText(Path.Combine(paths));
var card = AdaptiveCard.FromJson(cardJson).Card;
var columnSet = (card.Body[0] as AdaptiveColumnSet);
var column = (columnSet.Columns[0] as AdaptiveColumn);
var knowledgeBlock = (column.Items[1] as AdaptiveTextBlock);
knowledgeBlock.Text = "Whatever You Want";

var attachment = new Attachment()
{
    Content = card,
    ContentType = "application/vnd.microsoft.card.adaptive"
};

var reply = stepContext.Context.Activity.CreateReply();
reply.Attachments = new List<Attachment>();

reply.Attachments.Add(attachment);

await stepContext.Context.SendActivityAsync(reply);

Result:

enter image description here

2. Use Data Binding (in Preview)

This is in preview and you still need to use the NuGet package from #1, but makes it easier to modify particular fields.

3. Edit the JSON with Newtonsoft.JSON

This is probably a little simpler, but less flexible. Something like this works and produces the same result as #1:

string[] paths = { ".", "AdaptiveCard.json" };
var cardJsonObject = JObject.Parse(File.ReadAllText(Path.Combine(paths)));
var knowledgeToken = cardJsonObject.SelectToken("body[0].columns[0].items[1]");
knowledgeToken["text"] = "Whatever You Want";

var attachment = new Attachment()
{
    Content = cardJsonObject,
    ContentType = "application/vnd.microsoft.card.adaptive"
};

var reply = stepContext.Context.Activity.CreateReply();
reply.Attachments = new List<Attachment>();

reply.Attachments.Add(attachment);


await stepContext.Context.SendActivityAsync(reply);
return await stepContext.NextAsync();

Dynamically Changing After Being Displayed

Changing the card after being displayed is a little more difficult. You first have to change the card in the code, as done above. You then have to use UpdateActivityAsync(). Basically, you send an activity with the same id, but a new card and it overwrites the previous card completely.

Note: You can only use this in channels that support updating activities. It's usually pretty easy to tell, because even without bots, the channel either will or won't let you edit messages. It sounds like you want to use Teams, so this will work fine.

You can use my answer here for how to update card activities with Teams. Note that this one is in Node, but you can still do it in C# the same way.

You can also use this other StackOverflow Answer from one of the guys on the MS Teams team.

mdrichardson
  • 7,141
  • 1
  • 7
  • 21
  • Could you say whether it is possible to update an Adaptive Card that belongs to Messaging Extension response? Let's say that a user has shared an adaptive card in a chat. The card has a button "Comment" and a Text Input. When a user enters a comment, they can hit "Comment" and comment will be posted to the backend. After it I want to give a feedback to user, that everything is fine. For example, I can replace the original card with a card saying "Your comment has been posted". How can I do it? turnContext.UpdateActivity() doesn't wokr. It returns 400 – Kostya Vyrodov Nov 22 '20 at 20:25