-
Notifications
You must be signed in to change notification settings - Fork 592
Description
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
App insights exception tracking of rest data from mobile clients
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
}