I'm developing a program to extend some functionality from our helpdesk software to Microsoft Teams, using a connector.
This card will have a dropdown-menu where you can choose which person to assign the case to.
The card is successfully posted, but when i click the dropdown menu in the card nothing happens. I know the display-value pair is correctly set, because if I set "isMultiSelect" to true it displays my choices (but this is not going to be multi select, so I cant have it).
Here is the code example from Microsoft I'm using, look at the "Example connector message" - and below is my JSON. I believe it is correct according to the example.
JSON:
{
"summary": "my summary",
"title": "Main title",
"sections": [
{
"activitySubtitle": "ActivitySubtitle",
"activityImage": "http://www.ironmagazine.com/wp-content/uploads/arnold-schwarzenegger-420x327.jpg",
"activityTitle": "ActivityTitle",
"activityText": "ActivityText"
},
{
"facts": [
{
"value": "Facts1 - value",
"name": "Facts1 - name"
},
{
"value": "Facts2 - value",
"name": "Facts2 - name"
}
],
"title": "See more - Tittel "
}
],
"potentialAction": [
{
"actions": [
{
"name": "Add comment",
"target": "http://www.vg.no",
"#type": "HttpPost"
}
],
"inputs": [
{
"target": "https://www.vg.no",
"id": "Comment",
"#type": "TextInput"
}
],
"name": "Add comment",
"#type": "Actioncard"
},
{
"actions": [
{
"name": "Save",
"target": "http://www.vg.no",
"#type": "HttpPost"
}
],
"inputs": [
{
"title": "enter a due date",
"id": "dueDate",
"#type": "DateInput"
}
],
"name": "Set due date",
"#type": "Actioncard"
},
{
"actions": [
{
"name": "Save",
"target": "http://www.vg.no",
"#type": "HttpPost"
}
],
"inputs": [
{
"title": "Assign case to..",
"isMultiSelect": "false",
"choices": [
{
"value": "1",
"display": "Person1"
},
{
"value": "2",
"display": "Person2"
},
{
"value": "3",
"display": "Person3"
},
{
"value": "4",
"display": "Person4"
}
],
"id": "list",
"#type": "MultichoiceInput"
}
],
"name": "Assign case",
"#type": "Actioncard"
}
],
"text": "Main text"
}
Here is how my card is looking now: Imgur
Can anyone tell me what I am doing wrong - or perhaps there is a bug here?
Thanks in advance,
Arve
I was trying the JSON payload and it worked fine. Please try this paylod once and let us know if you still see the issue.
{
"summary": "my summary",
"title": "Main title",
"sections": [{
"activitySubtitle": "ActivitySubtitle",
"activityImage": "http://www.ironmagazine.com/wp-content/uploads/arnold-schwarzenegger-420x327.jpg",
"activityTitle": "ActivityTitle",
"activityText": "ActivityText"
}, {
"facts": [{
"value": "Facts1 - value",
"name": "Facts1 - name"
}, {
"value": "Facts2 - value",
"name": "Facts2 - name"
}
],
"title": "See more - Tittel "
}
],
"potentialAction": [{
"actions": [{
"name": "Add comment",
"target": "http://www.vg.no",
"#type": "HttpPOST"
}
],
"inputs": [{
"target": "https://www.vg.no",
"id": "Comment",
"#type": "TextInput"
}
],
"name": "Add comment",
"#type": "ActionCard"
}, {
"actions": [{
"name": "Save",
"target": "http://www.vg.no",
"#type": "HttpPOST"
}
],
"inputs": [{
"title": "enter a due date",
"id": "dueDate",
"#type": "DateInput"
}
],
"name": "Set due date",
"#type": "ActionCard"
}, {
"actions": [{
"name": "Save",
"target": "http://www.vg.no",
"#type": "HttpPOST"
}
],
"inputs": [{
"title": "Assign case to..",
"isMultiSelect": "false",
"choices": [{
"value": "1",
"display": "Person1"
}, {
"value": "2",
"display": "Person2"
}, {
"value": "3",
"display": "Person3"
}, {
"value": "4",
"display": "Person4"
}
],
"id": "list",
"#type": "MultichoiceInput"
}
],
"name": "Assign case",
"#type": "ActionCard"
}
],
"text": "Main text"}
Regards,
Vasant
Related
We are working on a cross-platform bot. Adaptive card buttons doesn't seems to respond in MS Teams when used on iOS mobile. There is no response from bot at all. The card responds as expected when MS Teams is accessed via web browser or MS Teams application on desktop computer or via Android devices.
Here is the JSON, of which the text is replaced run-time.
{
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"text": "<heading>",
"wrap": true
}
]
},
{
"type": "Container",
"items": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "<Option1>",
"horizontalAlignment": "Center",
"weight": "Light",
"separator": true,
"color": "Accent"
}
],
"id": "1",
"selectAction": {
"type": "Action.Submit",
"title": "actionButton",
"data": {
"msteams": {
"type": "imBack",
"value": "{3}"
}
}
},
"horizontalAlignment": "Center",
"style": "emphasis"
},
{
"type": "Column",
"width": "stretch",
"separator": true,
"items": [
{
"type": "TextBlock",
"text": "<Option2>",
"horizontalAlignment": "Center",
"weight": "Light",
"separator": true,
"color": "Accent"
}
],
"id": "2",
"selectAction": {
"type": "Action.Submit",
"title": "actionButton",
"data": {
"msteams": {
"type": "imBack",
"value": "{4}"
}
}
},
"horizontalAlignment": "Center",
"style": "emphasis"
}
]
}
]
}
],
"$schema": "http:adaptivecards.ioschemasadaptive-card.json"
}
I doubt this is the actual cause, but your schema is wrong - it should be:
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json"
Can somebody please help me, what is wrong with this card?
It works in https://adaptivecards.io/designer/ but I get this exception when trying in my bot in emulator:
Exception thrown: 'Jurassic.JavaScriptException' in Jurassic.dll
Exception thrown: 'Jurassic.JavaScriptException' in
System.Private.CoreLib.dll
Microsoft.Bot.Builder.Integration.AspNet.Core.BotFrameworkHttpAdapter:Error: Exception caught : Error: Invalid value type: undefined
The exception occurs when I try to transform the template and the data:
var cardJson = transformer.Transform(cardtemplate, carddata);
The carddata is an empty json in my test. In production, I can receive different responses (like: hit, miss or gameover), where some of the data is missing.
Update: I think, I narrowed it down, the problem seems that the engine doesn't like if a referenced data is missing in the $when property like:
"$when": "{result.shipStatus== 'HIT'}". Is there any workaround for this issue, that can be solved inside the card, or with very small change in the code? Like a propert to handle missing data as false?
card json:
{
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "Container",
"id": "playing",
"items": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "Shots: {result.score.nrMoves}"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "Hits: {result.score.nrHits}"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "Missed: {result.score.nrMisses}"
}
]
}
]
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "{result.shipStatus}",
"horizontalAlignment": "Center",
"height": "stretch",
"color": "{if(result.shipStatus == 'HIT', 'good', 'attention')}",
"size": "ExtraLarge"
}
],
"horizontalAlignment": "Center"
}
],
"separator": true
},
{
"type": "Container",
"$when": "{result.shipStatus== 'HIT'}",
"items": [
{
"type": "TextBlock",
"text": "{result.hitShip.name}",
"size": "Large",
"weight": "Bolder",
"color": "Accent",
"horizontalAlignment": "Center"
}
]
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "Target:",
"horizontalAlignment": "Right",
"height": "stretch",
"weight": "Bolder",
"size": "Medium"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "Input.Text",
"placeholder": "A1",
"value": "",
"id": "id_x"
}
]
}
]
},
{
"type": "ActionSet",
"id": "",
"actions": [
{
"type": "Action.Submit",
"title": "Shoot",
"id": "",
"style": "positive",
"data": {
"action": "shoot"
}
}
]
}
],
"$when": "{result.gameProgress == 'PLAYING'}"
},
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"text": "Game Over!",
"color": "Accent",
"size": "ExtraLarge",
"fontType": "Monospace",
"weight": "Bolder",
"horizontalAlignment": "Center"
}
],
"id": "gameover",
"$when": "{result.gameProgress == 'GAMEOVER'}"
},
{
"type": "Input.Text",
"value": "{result.gameUid}",
"size": "Small",
"wrap": true,
"id": "GameID",
"isVisible": false
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json"
}
I am trying to find a way to sum the prices held in an array, the way I am doing it now is to save the document to CosmosDB then run an additional sum(foo) query on it but I am thinking there must be a way so simply do that directly before I save the document to CosmosDB to save the extra round trip to the DocumentDB.
Example Document below.
The values I want to summarise are under:
ApiInputObject.TransactionDetails.Items.Price and there can of course be many items in the array.
I can only figure out how to get a single value out but that seems very inefficient.
{
"InternalTransactionlId": "XXX",
"DocumentType": "order",
"ExternalTransactionId": "externalIdTest2",
"OrderBotResponse": {
"id": "XXX",
"status": "pending",
"checkoutUrl": "https://www.example.com",
"items": [
{
"attributes": {
"color": "Midnight blue",
"size": "L"
},
"price": "500",
"quantity": "1",
"shipping": "0.0",
"title": "ACME Title",
"url": "https://example.com",
"product_id": "XXX",
"imageUrl": "https://example.com/image.jpg",
"status": "pending",
"shippingMethod": "default",
"totalPrice": 500
}
],
"reference": "XXX",
"currency": "SEK",
"country": "SE",
"language": "sv-se",
"provider": "acme",
"callback": {
"refund": "http://example.com",
"success": "http://example.com"
},
"shippingAddress": {},
"logs": [
{
"t": "2019-08-24T20:58:04.844+08:00",
"m": "Created"
}
],
"meta": {
"error": 0
}
},
"ApiInputObject": {
"ApiKey": "XXX",
"OrderType": "directTransaction",
"SourceSystem": {
"SourceSystemName": "ACME"
},
"SourceSystemCountry": "SE",
"DestinationSystem": {
"DestinationSystemName": "acme.com"
},
"DestinationSystemCountry": {
"DestinationSystemCountryName": "SE"
},
"Brand": {
"BrandName": "ACME"
},
"RequestedFeatures": [
"NONE"
],
"ExternalTransactionId": "externalIdTest2",
"TransactionDetails": {
"callback": {
"refund": "http://example.com",
"success": "http://example.com"
},
"items": [
{
"attributes": {
"color": "Midnight blue",
"size": "L"
},
"price": "500",
"quantity": "1",
"shipping": "0.0",
"title": "ACME",
"url": "https://example.com"
}
],
"test": "true",
"reference": "XXX"
}
},
"id": "XXX",
"_rid": "XXX",
"_self": "XXX",
"_etag": "XXX",
"_attachments": "attachments/",
"_ts": 111
}
You can try to use SelectToken to get your JSON data value. then use linq SUM
JObject obj = JObject.Parse(data);
var value = obj.SelectToken("ApiInputObject.TransactionDetails.items").Sum(x=>((int)x["price"]));
c# online
I have generated an adaptive card using JSON format with two buttons submit and cancel which are returning a "messageBack" message as submit and cancel respectively.
I am using C# to access the reply but I am not able to figure out how to access the reply from the adaptive card.
My json is
{
"type": "AdaptiveCard",
"selectAction": {
"type": "Action.Submit"
},
"body": [
{
"type": "TextBlock",
"horizontalAlignment": "Center",
"size": "Large",
"weight": "Bolder",
"color": "Accent",
"text": "Meeting Composer Create"
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"horizontalAlignment": "Left",
"spacing": "Medium",
"size": "Medium",
"weight": "Bolder",
"color": "Accent",
"text": "Attendees:"
}
],
"width": "stretch"
},
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"id": "attendeeVal",
"text": "a"
}
],
"width": "stretch"
}
]
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"size": "Medium",
"weight": "Bolder",
"color": "Accent",
"text": "Subject:"
}
],
"width": "stretch"
},
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"id": "subVal",
"text": "meeting"
}
],
"width": "stretch"
}
]
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"size": "Medium",
"weight": "Bolder",
"color": "Accent",
"text": "Date:"
}
],
"width": "stretch"
},
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"id": "dateVal",
"text": "17/11/2018 10.30 AM"
}
],
"width": "stretch"
}
]
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"size": "Medium",
"weight": "Bolder",
"color": "Accent",
"text": "Document Name:"
}
],
"width": "stretch"
},
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"id": "docVal",
"text": "Document1"
}
],
"width": "stretch"
}
]
}
],
"actions": [
{
"type": "Action.Submit",
"title": "Submit",
"data": {
"msteams": {
"type": "messageBack",
"displayText": "I clicked this button",
"text": "text to bots",
"value": "Submit"
}
}
},
{
"type": "Action.Submit",
"title": "Cancel",
"data": {
"msteams": {
"type": "messageBack",
"displayText": "I clicked this button",
"text": "text to bots",
"value": "Cancel"
}
}
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.0"
}
my C# is
var response = getCard(stepContext, "Aditya Rao, Vishal Subramaniam" , "Scrum Meeting" , "17/11/1028, 10:30AM" , "Scrum Sprint.pptx");
await stepContext.Context.SendActivityAsync(response).ConfigureAwait(false);
my additional function to support are
private static Attachment CreateAdaptiveCardAttachment(string filePath, string names, string subj , string datee, string docs)
{
var adaptiveCardJson = File.ReadAllText(filePath);
dynamic obj = JsonConvert.DeserializeObject(adaptiveCardJson);
obj["body"][1]["columns"][1]["items"][0]["text"] = names;
obj["body"][2]["columns"][1]["items"][0]["text"] = subj;
obj["body"][3]["columns"][1]["items"][0]["text"] = datee;
obj["body"][4]["columns"][1]["items"][0]["text"] = docs;
var adaptiveCardAttachment = new Attachment()
{
ContentType = "application/vnd.microsoft.card.adaptive",
Content = obj,
};
return adaptiveCardAttachment;
}
// Create an attachment message response.
private Activity CreateResponse(Activity activity, Attachment attachment)
{
var response = activity.CreateReply();
response.Attachments = new List<Attachment>() { attachment };
return response;
}
private Activity getCard(WaterfallStepContext stepContext, string names, string subj , string datee, string docs)
{
var jsonFilePath = #".\Dialogs\CardTemplates\MeetingComposerCreate.json";
var activity = stepContext.Context.Activity;
var adCard = CreateAdaptiveCardAttachment(jsonFilePath,names,subj,datee,docs);
var response = CreateResponse(activity, adCard);
return response;
}
How do I access the values response once submit or cancel is clicked?
Also if someone can help me find how to get reply from input.choice to get the checkbox data of the selected cards.
How do I access the values response once submit or cancel is clicked?
We can get the value that user submit from adaptive card via Activity.Value property.
if(turnContext.Activity.Value!= null)
{
reply.Text = $"submit data: {turnContext.Activity.Value}";
}
Test Result:
Output in emulator:
Also if someone can help me find how to get reply from input.choice to get the checkbox data of the selected cards.
To display choice options for user selecting and get the selected option, you can refer to the following code snippet.
In json file:
{
"type": "Input.ChoiceSet",
"id": "optionSelection",
"isMultiSelect": true,
"style": "compact",
"choices": [
{
"title": "option1",
"value": "option1"
},
{
"title": "option2",
"value": "option2"
},
{
"title": "option3",
"value": "option3"
}
]
}
Using same code to get user's selection:
reply.Text = $"submit data: {turnContext.Activity.Value}";
Test Result:
I have this JSON:
{
"total": 23695,
"total_pages": 1185,
"results": [{
"id": "r7bVvV7MLdQ",
"created_at": "2018-01-17T06:38:03-05:00",
"updated_at": "2018-05-09T03:35:24-04:00",
"width": 4032,
"height": 2526,
"color": "#F7EDE7",
"description": null,
"urls": {
"raw": "https://images.unsplash.com/photo-1516189050082-44d4deb5ceef?ixlib=rb-0.3.5\u0026ixid=eyJhcHBfaWQiOjEyMDd9\u0026s=8b6caac6353f390fbbabde8441dd1959",
"full": "https://images.unsplash.com/photo-1516189050082-44d4deb5ceef?ixlib=rb-0.3.5\u0026q=85\u0026fm=jpg\u0026crop=entropy\u0026cs=srgb\u0026ixid=eyJhcHBfaWQiOjEyMDd9\u0026s=89ca725623d794116d3741907c93ceab",
"regular": "https://images.unsplash.com/photo-1516189050082-44d4deb5ceef?ixlib=rb-0.3.5\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=1080\u0026fit=max\u0026ixid=eyJhcHBfaWQiOjEyMDd9\u0026s=666eb6ac25c7fec68d5994545b933726",
"small": "https://images.unsplash.com/photo-1516189050082-44d4deb5ceef?ixlib=rb-0.3.5\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=400\u0026fit=max\u0026ixid=eyJhcHBfaWQiOjEyMDd9\u0026s=3dbc611c97d323ff8b4b043cff19317b",
"thumb": "https://images.unsplash.com/photo-1516189050082-44d4deb5ceef?ixlib=rb-0.3.5\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=200\u0026fit=max\u0026ixid=eyJhcHBfaWQiOjEyMDd9\u0026s=0c760185c35eadb31a7bba9b9794d424"
},
"links": {
"self": "https://api.unsplash.com/photos/r7bVvV7MLdQ",
"html": "https://unsplash.com/photos/r7bVvV7MLdQ",
"download": "https://unsplash.com/photos/r7bVvV7MLdQ/download",
"download_location": "https://api.unsplash.com/photos/r7bVvV7MLdQ/download"
},
"categories": [],
"sponsored": false,
"likes": 0,
"liked_by_user": false,
"current_user_collections": [],
"slug": "cloud-smoke-steam",
"user": {
"id": "G69mdFHx0X0",
"updated_at": "2018-05-03T14:00:07-04:00",
"username": "maxkuk",
"name": "Max Kukurudziak",
"first_name": "Max",
"last_name": "Kukurudziak",
"twitter_username": null,
"portfolio_url": "http://www.instagram.com/makckuk",
"bio": "Product Designer at MacPaw, Lecturer at Projector",
"location": "Kiev, Ukraine",
"links": {
"self": "https://api.unsplash.com/users/maxkuk",
"html": "https://unsplash.com/#maxkuk",
"photos": "https://api.unsplash.com/users/maxkuk/photos",
"likes": "https://api.unsplash.com/users/maxkuk/likes",
"portfolio": "https://api.unsplash.com/users/maxkuk/portfolio",
"following": "https://api.unsplash.com/users/maxkuk/following",
"followers": "https://api.unsplash.com/users/maxkuk/followers"
},
"profile_image": {
"small": "https://images.unsplash.com/profile-1518780839522-ee199eceaf8c?ixlib=rb-0.3.5\u0026q=80\u0026fm=jpg\u0026crop=faces\u0026cs=tinysrgb\u0026fit=crop\u0026h=32\u0026w=32\u0026s=c37d2f2844b45f52c0f66cd580a200c8",
"medium": "https://images.unsplash.com/profile-1518780839522-ee199eceaf8c?ixlib=rb-0.3.5\u0026q=80\u0026fm=jpg\u0026crop=faces\u0026cs=tinysrgb\u0026fit=crop\u0026h=64\u0026w=64\u0026s=93647049c20b6a323870fe0886eee329",
"large": "https://images.unsplash.com/profile-1518780839522-ee199eceaf8c?ixlib=rb-0.3.5\u0026q=80\u0026fm=jpg\u0026crop=faces\u0026cs=tinysrgb\u0026fit=crop\u0026h=128\u0026w=128\u0026s=aff2d13afe9fe418b562b85c226b7e8e"
},
"instagram_username": "makckuk",
"total_collections": 0,
"total_likes": 6,
"total_photos": 56
},
"tags": [{
"title": "cloud"
},
{
"title": "smoke"
},
{
"title": "steam"
},
{
"title": "mountain"
},
{
"title": "volcano"
},
{
"title": "blue"
},
{
"title": "rock"
},
{
"title": "glacier"
},
{
"title": "field"
},
{
"title": "geysir"
},
{
"title": "iceland"
}],
"photo_tags": [{
"title": "cloud"
},
{
"title": "smoke"
},
{
"title": "steam"
},
{
"title": "mountain"
},
{
"title": "volcano"
},
{
"title": "blue"
},
{
"title": "rock"
},
{
"title": "glacier"
},
{
"title": "field"
},
{
"title": "geysir"
},
{
"title": "iceland"
}]
},
I need to get results.profile_image.small I tried it on many ways but I never figured out how to access to profile_image fields.
Basically I want to do something like this:
dynamic array = JsonConvert.DeserializeObject(responz);
foreach (var itemx in array["results"])
{
MessageBox.Show(itemx.profile_image.small.ToString());
}
I spent last few hours figuring it out, searching searching StackOverflow. The last option is do this with regex which would be very stupid thing to do.
Based on your JSON, the actual path should be:
itemx.user.profile_image.small
So if you modify your code to include the missing "user" portion:
dynamic array = JsonConvert.DeserializeObject(responz);
foreach (var itemx in array["results"])
{
MessageBox.Show(itemx.user.profile_image.small.ToString());
}
That should solve your problem.
However, this problem would likely not have presented itself if you were using a concrete class to deserialize into. You would have type safety and the assistance of Intelisense if you use a concrete class. You can easily convert your JSON sample into a concrete class using Json2CSharp or using the "Paste as Class" function of modern Visual Studio versions.