Skip to content

[Bug]: Adaptive cards not sending payload data from iOS Teams Mobile app #9330

@whites2015

Description

@whites2015

Target Platforms

iOS

SDK Version

3.1.0

Application Name

Microsoft Teams (IOS mobile)

Problem Description

I have a MS Teams chat bot that utilises adaptive cards for visualisation and data collection.
The feature having the issue is a subscription configuration card that recently started writing null values to the database for fields that should not be null as the are required.
These null values started appearing from December 16th.
No change in the card payload or data model occurred prior to the issue being noticed.
Desktop version in Windows and Mac OS works as expected with no null values

App Versions

  • Desktop - 25198.1112.3855.290, Windows 11 Enterprise, Version 23H2
  • Desktop - MAC OS Tahoe
  • Mobile - 7.22.2, iOS 26.2
  • Adaptive card schema version v1.3

Packages

  • "AdaptiveCards": "3.1.0",
  • "AdaptiveCards.Templating": "2.0.5",
  • "Microsoft.Bot.Builder.Azure": 4.23.0,
  • "Microsoft.Bot.Builder.Dialogs": 4.23.0
  • "Microsoft.Bot.Builder.Integration.AspNet.Core": 4.23.0

Screenshots

Image

App insights exception tracking of rest data from mobile clients

Image

Card JSON

{
  "type": "AdaptiveCard",
  "version": "1.3",
  "body": [
    {
      "type": "TextBlock",
      "text": "ViDA Messaging Configuration",
      "horizontalAlignment": "Center",
      "weight": "Bolder",
      "size": "Medium"
    },
    {
      "type": "TextBlock",
      "text": "${name}",
      "weight": "Bolder",
      "horizontalAlignment": "Center"
    },
    {
      "id": "notificationoptions",
      "type": "Input.ChoiceSet",
      "choices": [
        {
          "title": "Insights",
          "value": "insights"
        },
        {
          "title": "Live Faults",
          "value": "livefaults"
        }
      ],
      "isMultiSelect": true,
      "label": "Notifications",
      "value": "${NotificationOptions}",
      "style": "expanded"
    },
    {
      "type": "Input.ChoiceSet",
      "placeholder": "Placeholder text",
      "choices": [
        {
          "title": "Tuesday",
          "value": "tuesday"
        },
        {
          "title": "Wednesday",
          "value": "wednesday"
        },
        {
          "title": "Thursday",
          "value": "thursday"
        },
        {
          "title": "Friday",
          "value": "friday"
        },
        {
          "title": "Saturday",
          "value": "saturday"
        }
      ],
      "style": "expanded",
      "value": "${lowpriority}",
      "id": "lowpriority",
      "isMultiSelect": true,
      "label": "<redacted>",
      "spacing": "Medium"
    },
    {
      "type": "Input.ChoiceSet",
      "choices": [
        {
          "title": "<redacted>",
          "value": "all"
        },
        {
          "title": "<redacted>",
          "value": "option1"
        }
      ],
      "value": "${style}",
      "id": "style",
      "placeholder": "Not Set",
      "isRequired": true,
      "errorMessage": "<redacted>",
      "label": "<redacted>",
      "spacing": "Medium"
    },
    {
      "type": "Input.Text",
      "placeholder": "<redacted>",
      "isMultiline": true,
      "separator": true,
      "id": "<redacted>",
      "value": "${m}",
      "isRequired": true,
      "errorMessage": "<redacted>",
      "label": "<redacted>",
      "spacing": "Medium"
    },
    {
      "type": "Input.ChoiceSet",
      "errorMessage": "<redacted>",
      "choices": [
        {
          "title": "None",
          "value": "None"
        },
        {
          "title": "<redacted>",
          "value": "<redacted>"
        },
        {
          "title": "<redacted>",
          "value": "<redacted>"
        }
      ],
      "label": "<redacted>",
      "id": "<redacted>",
      "value": "<redacted>",
      "isRequired": true
    },
    {
      "type": "Input.ChoiceSet",
      "placeholder": "select a timezone",
      "choices": [
        {
          "title": "GMT-8\tPacific Standard Time (PST)",
          "value": "-8"
        },
        {
          "title": "GMT-6\tCentral Standard Time (CST)",
          "value": "-6"
        },
        {
          "title": "GMT-5\tEastern Standard Time (EST)",
          "value": "-5"
        },
        {
          "title": "GMT+0\tGreenwich Mean Time (GMT)",
          "value": "0"
        },
        {
          "title": "GMT +1\tCentral European Time (CET)",
          "value": "1"
        },
        {
          "title": "GMT +3\tMoscow Time (MSK)",
          "value": "+3"
        },
        {
          "title": "GMT +5.5\tIndia Standard Time (IST)",
          "value": "5.5"
        },
        {
          "title": "GMT +8\tChina Standard Time (CST)",
          "value": "8"
        },
        {
          "title": "GMT +9\tJapan Standard Time (JST)",
          "value": "9"
        },
        {
          "title": "GMT +12\tNew Zealand Standard Time (NZST)",
          "value": "12"
        }
      ],
      "value": "${timezone}",
      "id": "timezone",
      "isRequired": true,
      "errorMessage": "Your time zone is required",
      "label": "Your Time Zone",
      "spacing": "Medium"
    },
    {
      "type": "Input.ChoiceSet",
      "placeholder": "Not Set",
      "choices": [
        {
          "title": "6.30AM",
          "value": "6.30AM"
        },
        {
          "title": "7.30AM",
          "value": "7.30AM"
        },
        {
          "title": "8.30AM",
          "value": "8.30AM"
        }
      ],
      "id": "sendtime",
      "value": "${sendingtime}",
      "isRequired": true,
      "errorMessage": "Your send time is required",
      "label": "Sending Time",
      "spacing": "Medium"
    },
    {
      "type": "ActionSet",
      "actions": [
        {
          "type": "Action.ShowCard",
          "title": "?",
          "card": {
            "type": "AdaptiveCard",
            "version": "1.3",
            "body": [
              {
                "type": "TextBlock",
                "text": "<redacted>",
                "wrap": true,
                "horizontalAlignment": "Left"
              },
              {
                "type": "TextBlock",
                "text": "**<redacted>",
                "wrap": true,
                "horizontalAlignment": "Left"
              },
              {
                "type": "TextBlock",
                "text": "**<redacted>",
                "wrap": true,
                "horizontalAlignment": "Left"
              },
              {
                "type": "TextBlock",
                "text": "<redacted>",
                "wrap": true,
                "horizontalAlignment": "Left"
              },
              {
                "type": "TextBlock",
                "text": "<redacted>",
                "wrap": true,
                "horizontalAlignment": "Left"
              },
              {
                "type": "TextBlock",
                "text": "**Your Time Zone:** \n\r  Select the nearest TimeZone/GMT offset of your location",
                "wrap": true,
                "horizontalAlignment": "Left"
              },
              {
                "type": "TextBlock",
                "text": "**Sending Time:** \n\r Requested email send time, used in conjunction with Timezone information",
                "wrap": true,
                "horizontalAlignment": "Left"
              }
            ],
            "$schema": "https://adaptivecards.io/schemas/adaptive-card.json"
          },
          "style": "positive"
        }
      ]
    },
    {
      "type": "TextBlock",
      "text": "<redacted>",
      "wrap": true,
      "isSubtle": true
    },
    {
      "type": "ActionSet",
      "actions": [
        {
          "type": "Action.Submit",
          "title": "${submit}",
          "data": {
            "Update_Config": "true"
          },
          "associatedInputs": "auto"
        }
      ]
    }
  ],
  "$schema": "https://adaptivecards.io/schemas/adaptive-card.json"
}

Sample Code Language

C#

Sample Code

Send card

var user = await Database.GetConfiguration(cancellationToken, member.Email.ToLower());

ConfResult displayableConfig = user != null ? new ConfResult(user) : new ConfResult(member.Email);
string card = await File.ReadAllTextAsync(@"Cards\Configuration.json", cancellationToken);

// Add delete button dynamically
if (user != null)
{
var button =
$@"{{""type"":""Action.Submit"",""title"":""Delete Subscription"",""data"":{{""Delete_Config"":""true""}},""mode"":""secondary"",""style"":""destructive""}}";
var parsedJson = JObject.Parse(card);
var parsedButton = JObject.Parse(button);
parsedJson["body"]?.Last["actions"].Last.AddAfterSelf(parsedButton);
card = parsedJson.ToString();
}

var dat = JsonConvert.SerializeObject(displayableConfig);
var transformer = new AdaptiveCardTemplate(card);
var adaptiveCardJson = transformer.Expand(dat);

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

await turnContext.SendActivityAsync(MessageFactory.Attachment(cardAttachment), cancellationToken);

Receive card data

var user = new User(new ConfResult(rest), member.Email)
{
Name = $"{member.GivenName} {member.Surname}",
GivenName = member.GivenName,
Surname = member.Surname,
Conversation = turnContext.Activity.GetConversationReference(),
Locale = turnContext.Activity.Locale,
TimeZoneOffset = timeZoneOffset.ToString()
};

if(user.SubscribedDistrict == null)
{
#if !DEBUG
await turnContext.DeleteActivityAsync(turnContext.Activity.ReplyToId, cancellationToken);
#endif
await turnContext.SendActivityAsync($"Configuration Update FAILED! - if using mobile device, try using desktop Teams application or contact support");
return;
}
#if !DEBUG
user.UserPrinciple = member.UserPrincipalName;
await turnContext.DeleteActivityAsync(turnContext.Activity.ReplyToId, cancellationToken);
#endif
var success = await Database.UpdateSubscriberItemAsync(turnContext, cancellationToken, user);
if (success)
await turnContext.SendActivityAsync($"Configuration Updated", cancellationToken: cancellationToken);
else
await turnContext.SendActivityAsync("Fault updating subscription, try again or contact support", cancellationToken: cancellationToken);
}
catch (Exception e)
{
#if !DEBUG
IDictionary<string, string> properties = new Dictionary<string, string>
{
["Type"] = "Updating User configuration",
["UserEmail"] = member.Email,
["UserName"] = $"{member.GivenName} {member.Surname}",
["rest"] = rest.ToString(),
["activityvalue"] = JsonConvert.SerializeObject(turnContext.Activity.Value)
};
AzureTelemetry.TelemetryClient.TrackException(e, properties);
#endif
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions