ASP.NET WebHooks and Slack Slash Commands

We just added a couple of new features in ASP.NET WebHooks that makes it easier to build some nice integrations with Slack Slash Commands. These commands make it possible to trigger any kind of processing from a Slack channel by generating an HTTP request containing details about the command. For example, a command typed in a Slack channel can be configured to send an HTTP request to an ASP.NET WebHook endpoint where processing can happen:

/henrik Remember to buy flowers!

As usual, you can get ASP.NET WebHooks from Nuget – look for beta6b with the preview flag turned on in Visual Studio. If you are new to ASP.NET WebHooks, then check out the blog Introducing Microsoft ASP.NET WebHooks Preview.

Parsing Slack Commands

In the post Updates to Microsoft ASP.NET WebHooks Preview we described the basics of how to use ASP.NET WebHooks with Slash Commands. That used a simple string to trigger the command without going into detail with what the command would look like. However, what if you want to build a Slash Command that can manage a list of users like this:

/list add <user>
/list list
/list remove <user>

To do this you have to parse the command and split out the action from the parameter. To make this simple, we provide you with the SlackCommand helper class for doing this. In an ASP.NET WebHooks handler, you can use this to process the command like this:

public class SlackWebHookHandler : WebHookHandler
{
public SlackWebHookHandler()
{
this.Receiver = SlackWebHookReceiver.ReceiverName;
}

public override Task ExecuteAsync(string generator, WebHookHandlerContext context)
{
// Get Slash Command data as a name value collection
var command = context.GetDataOrDefault<NameValueCollection>();

// Parse the text of the form 'action parameter'.
var slashCommand = SlackCommand.ParseActionWithValue(command["text"]);

// Look at action and parameter
string action = slashCommand.Key;
string parameter = slashCommand.Value;

return Task.FromResult(true);
}
}


In the example above there is only one parameter (the user), but you can imagine many scenarios where you’d want to pass multiple parameters. For example, you may want a list of action items where each item can be assigned to a user like this:

/list add title=Remember to buy flowers!; assignedTo: henrik
/list list

Here we have the add action with two parameters separated by a semi-colon: title and assignedto, each with their own value. We also provide help for doing this following a similar pattern:

public class SlackWebHookHandler : WebHookHandler
{
public SlackWebHookHandler()
{
this.Receiver = SlackWebHookReceiver.ReceiverName;
}

public override Task ExecuteAsync(string generator, WebHookHandlerContext context)
{
// Get Slash Command data as a name value collection
var command = context.GetDataOrDefault<NameValueCollection>();

// Parse the text of the form 'action p1=v1; p2=v2; ...'.
var slashCommand = SlackCommand.ParseActionWithParameters(command["text"]);

// Look at action and parameters
string action = slashCommand.Key;
NameValueCollection parameters = slashCommand.Value;

return Task.FromResult(true);
}
}


Responding with Data, Images, and More

Just like it is possible to pass more complex commands, it is also possible to respond with structured data and even to include tabular data, images, and more. To facilitate this we have added the SlackSlashResponse class which helps you build a response to send back to Slack. In its simplest form, it takes just a string but you can add attachments to it containing structured text, tabular data, and images:

public class SlackWebHookHandler : WebHookHandler
{
public SlackWebHookHandler()
{
this.Receiver = SlackWebHookReceiver.ReceiverName;
}

public override Task ExecuteAsync(string generator, WebHookHandlerContext context)
{
// Information can be returned using a SlackSlashResponse
var slashReply = new SlackSlashResponse("Hello from ASP.NET WebHooks!");

// Slash replies can be augmented with attachments containing data, images, and more
// The fallback description is used in clients that can only show plain-text replies.
var att = new SlackAttachment("Attachment Text", "Fallback description")
{
Color = "#439FE0",
Pretext = "This is an attachment!",
Title = "Attachment title",
ImageLink = new Uri("http://www.example.com"),
};

// Slash attachments can contain tabular data as well
att.Fields.Add(new SlackField("Field1", "1234"));
att.Fields.Add(new SlackField("Field2", "5678"));

// A reply can contain multiple attachments
slashReply.Attachments.Add(att);

// Return slash command response
context.Response = context.Request.CreateResponse(slashReply);

return Task.FromResult(true);
}
}

Slack requires a response to be sent within 3 seconds of the request but it does have a model for responding asynchronously later using a special URI where you can post data for up to 30 mins after the command was first sent, see Slash Commands for details. ASP.NET WebHooks support this either by running a Task directly from the handler or by queuing the WebHook for delayed processing by another process.

Trying it out

We provide a sample that shows both parsing commands and generating responses using the same model as outlined above. By setting up the Slash Command as described in the blog Updates to Microsoft ASP.NET WebHooks Preview and publishing an ASP.NET WebHook Slack Receiver with a handler like above you can get a structured response similar to this:

SlashCommandReply1

That’s it! Now you can process complex Slack Slash Commands and generate structured responses!

Happy Valentine’s Day!

Henrik