Search code examples
c#botframeworkslackslack-api

Properly format a message for slack in bot framework


I'd like to send a message with buttons to the slack channel. I'm using the bot framework (c#). I want to use the "blocks" (attachments are deprecated according to the slack api docs). So I composed a sample message in the slack "Bot Kit Builder":

message

The json for it looks like this:

[
    {
        "type": "section",
        "text": {
            "type": "mrkdwn",
            "text": "Which pill do you want to take?"
        }
    },
    {
        "type": "actions",
        "elements": [
            {
                "type": "button",
                "text": {
                    "type": "plain_text",
                    "text": "Red",
                    "emoji": true
                },
                "value": "red"
            },
            {
                "type": "button",
                "text": {
                    "type": "plain_text",
                    "text": "Blue",
                    "emoji": true
                },
                "value": "blue"
            }
        ]
    }
]

As I understand, I have to provide this content in the ChannelData property of the message I sent to the channel:


if (turnContext.Activity.ChannelId == Channels.Slack)
{
   message = turnContext.Activity.CreateReply();
   message.ChannelData = ChannelDataBuilder.Create("Which pill do you want to take?", "Red", "Blue");
}

The code of the ChannelDataBuilder looks like this:

public static dynamic Create(string text, params string[] choices)
{
   var blocks = new List<Block> { new Section { Text = new Text { TextValue = text } } };
   var elements = choices.Select(
                c => new Button { Text = new Text { TextValue = c, Type = "plain_text" }, Value = c });
   blocks.Add(new Actions { Elements = elements.ToArray() });
   return JArray.FromObject(blocks, new JsonSerializer { NullValueHandling = NullValueHandling.Ignore });
}

The resulting json of this method looks like this:

{[
  {
    "type": "section",
    "text": {
      "type": "mrkdwn",
      "text": "Which pill do you want to take?"
    }
  },
  {
    "type": "actions",
    "elements": [
      {
        "type": "button",
        "text": {
          "type": "plain_text",
          "text": "Red"
        },
        "action_id": "9e8ea9fb9267484a9f02b1837f716f69",
        "value": "Red"
      },
      {
        "type": "button",
        "text": {
          "type": "plain_text",
          "text": "Blue"
        },
        "action_id": "34c3d9509fc04e2ea37ed54a70b78486",
        "value": "Blue"
      }
    ]
  }
]}

So, basically I wonder how I should generate this array of json object using c#. Currently the array is still surrounded by the curly brackets (the list object), but I guess I have to provide an array of json objects.

I've already tried using the JsonConvert class and setting the ChannelData as string. But then nothing appears in the slack channel.


Solution

  • The channelData property allows you to pass a complete Slack message, but your are missing the required top-level properties.

    If you want to include blocks, than those have to be defined under the blocks property.

    So your JSON need to look more like this (not include the channelData property):

    {
        "blocks": 
        [
            {
                "type": "section",
                "text": {
                "type": "mrkdwn",
                "text": "Which pill do you want to take?"
                }
            },
            {
                "type": "actions",
                "elements": [
                {
                    "type": "button",
                    "text": {
                    "type": "plain_text",
                    "text": "Red"
                    },
                    "action_id": "9e8ea9fb9267484a9f02b1837f716f69",
                    "value": "Red"
                },
                {
                    "type": "button",
                    "text": {
                    "type": "plain_text",
                    "text": "Blue"
                    },
                    "action_id": "34c3d9509fc04e2ea37ed54a70b78486",
                    "value": "Blue"
                }
                ]
            }
        ]
    }
    

    See here for the relevant documentation for the botframework.

    And here you can see how a message payload for Slack is defined.

    Update

    As mentioned by @mdrichardson the botframework currently does not support blocks. (See this issue on their github)

    So while syntactically correct this solutions does currently not work.

    Until botframework supports blocks I would suggest to use secondary attachments.