node.jsbotframeworkmicrosoft-teamsadaptive-cardsweb-chat

Can't get imBack to work on Adaptive Cards that are set up to work with teams


My bot has a menu card which I recently discovered doesn't work with teams. I want to use the imBack method to have the message show up in the chat. On their own, I can accomplish this with the following:

// For directline/webchat
"type": "Action.Submit",
"title": "Get Order Status",
"data": "Get Order Status"
},

// For MS Teams
"type": "Action.Submit",
"title": "Get Order Status",
"data": {
    "msteams": {
        "type": "imBack",
        "value": "Get Order Status"
    },
},

However, if I use the directline/webchat version, I get a general bot error in Teams (I believe the error is because the button doesn't create an imBack message, thus LUIS query is empty and all my code referencing LUIS attributes like topIntent and score fail. Due to bot design LUIS needs to be called every turn.) Likewise, if I use Teams version I get a general bot error in directline/webchat for the same reason. At first I tried to add additional objects like the one I created for msteams for other channel IDs, but that didn't change the behavior. Based on the information here, I was able to add the text attribute and copy it from context.activity.value to context.activity.text via the following:

// In my card definition
"type": "Action.Submit",
"title": "Get Order Status",
"data": {
    "msteams": {
        "type": "imBack",
        "value": "Get Order Status"
    },
    "text": "Get Order Status"
},

// In my onMessage handler
if (context.activity.channelData.postBack) {
    context.activity.text = context.activity.value.text;
}

When I implement it this way, it does technically work in both channels. However, the menu selection (in this case Get Order Status) does not appear in the chat window as a message from the user (and by extension, doesn't show in the chat transcript) for directline/webchat channel (it does for Teams channel). I would really like this to behave in the same way as it does if I just have the text at the attribute for data in my directline/webchat only implementation. Is there any way to set up the card (e.g. via different format of the data object to have different data sent based on channel) and/or onMessage handler so that, on button click, the text is displayed in the chat window regardless of channel, and by extension that text will go through LUIS so that I don't get bot errors due to null LUIS attributes?

The one thought I had was to create a separate card helper for Teams and call it from my menu intent based on channelId, but I'd like a more elegant solution than that if it is possible, especially since I have several different cards with submit buttons like this.


Solution

  • Been struggling with this myself and came across a solution that works in Adaptive Card Templates.

    Add a ChannelType property (or something similar) to the data binding model object, and set it appropriately before calling .Expand and use "$when": "${<condition>}" in the Adaptive Card Template json:

     {
       "type": "ActionSet",
       "actions": [
        {
          "$when": "${$root.channelType == 'webchat'}",
          "type": "Action.Submit",
          "title": "Get Order Status",
          "data": "Get Order Status"
        },
        {
          "$when": "${$root.channelType == 'msteams'}",
          "type": "Action.Submit",
          "title": "Get Order Status",
          "data": {
              "msteams": {
                  "type": "imBack",
                  "value": "Get Order Status"
              },
         }
       ]
    }
    

    See Adaptive Cards Template Language - Conditional layout with $when