Make a Slack WebHook plugin with C# .Net, Nancy, and Ngrok.

This blog article will walk you through making a C# webhook plugin for Slack. We’ll be using Nancy to setup a small web service, and ngrok to expose our service publicly so Slack can call it.

First, make a new C# console application with Visual Studio, and install a few nuget packages. The interesting packages are Nancy, Nancy.Hosting.Self, and Slack.Webhooks.

Next, we need to create a NancyHost and start it up. You’ll want your console application’s main to look roughly like this:

        static void Main()
        {
            JsConfig.EmitLowercaseUnderscoreNames = true;
            JsConfig.IncludeNullValues = false;
            JsConfig.PropertyConvention = JsonPropertyConvention.Lenient;
            using (var host = new NancyHost(new Uri("http://localhost:1234")))
            {
                host.Start();
                Console.ReadLine();
            }
            return;
        }

When our application runs, it launches a service that listens on localhost:1234 for requests.

Of course, you’ll need some using statements like this:

using Nancy;
using Nancy.Hosting.Self;
using Nancy.ModelBinding;
using Newtonsoft.Json;
using ServiceStack.Text;
using Slack.Webhooks;

Since our application will be listening on localhost:1234, we need to add request handlers. For our slack webhook plugin examlpe, we just need to handle a post. We’ll create a WebhookModule class that inherrits from NancyModule, and has a Post handler like this code:

public class WebhookModule : NancyModule
{
public WebhookModule()
{
Post["/"] = _ =>
{
var model = this.Bind<HookMessage>();
var message = string.Empty;
SlackAttachment attachment = null;
message = string.Format("@{0} Hello", model.UserName);
if (!string.IsNullOrWhiteSpace(message))
{
SlackMessage sm = new SlackMessage { Text = message, Username = "MyChat.Bot.Greeting", IconEmoji = Emoji.Ghost };
if(attachment != null)
{
sm.Attachments = new List<SlackAttachment>();
sm.Attachments.Add(attachment);
}
return sm;
}
return null;
};
}
}

When Post is received, this will receive a HookMessage and respond with a “Hello User” message. That response will be received by Slack and should output the “Hello User” message to your slack chat channel.

Here are a few other classes you’ll need that define the HookMessage and some other Nancy boiler plate configuration:

    public class HookMessage
    {
        public string Token { get; set; }
        public string TeamId { get; set; }
        public string ChannelId { get; set; }
        public string ChannelName { get; set; }
        public string UserId { get; set; }
        public string UserName { get; set; }
        public string Text { get; set; }
        public string TriggerWord { get; set; }
    }
    public class TitleCaseFieldNameConverter : IFieldNameConverter
    {
        public string Convert(string fieldName)
        {
            return fieldName.ToTitleCase();
        }
    }
    public class Bootstrapper : DefaultNancyBootstrapper
    {
        protected override void ApplicationStartup(Nancy.TinyIoc.TinyIoCContainer container, Nancy.Bootstrapper.IPipelines pipelines)
        {
            container.Register<IFieldNameConverter, TitleCaseFieldNameConverter>();
            base.ApplicationStartup(container, pipelines);
        }
    }

At this point, you should be able to run your C# console application and be listening for Post requests on localhost:1234. Next, follow my ngrok block article to setup ngrok to expose your localhost:1234 service to a public address:

http://blog.novelessay.com/post/make-local-mysql-instance-publicly-available-for-a-mvc-net-website-with-ngrok

When your ngrok is ready to run, you can make your service publicly available by starting the ngrok service like this:

ngrok.exe http 1234

Lastly, you’ll need to go in to your Slack configuration, and setup an Outgoing Webhook. Look in the “Browse Apps” -> “Custom Integrations” -> “Outgoing WebHooks” section. You will probably discover it more tricky to find where it was than to actually configure it.

You need to configure which channels you want your webhook to interact with, set the ngrok address that your service is serving on, and provide a token that Slack will send. You should update your C# console application to check the token value, but that’s not entirely necessary for this system to work.

Here’s an example of how I have an Outgoing WebHook configured in Slack:

That’s everything! Give your Slack Bot a try. 

Make local MySQL or ElasticSearch instance publicly available for a MVC.Net website with NgRok

Background:

I have a GoDaddy hosting account for NovelEssay.com, and I want to use and provide a large data set (like a personal copy of Wikipedia). GoDaddy’s MySQL database limits are 1GB, which is good – but not awesome. I could host MySQL at home on my personal computer, but how could my GoDaddy MVC.Net project access the data without a public address on my local instance?

(Note: I use ngrok, but they are certainly not paying me to write about it. Please read the security disclaimer at the bottom of this article. Exposing local resources to the internet is awesome and will have extra security concerns.)

Introducting: NgRok

If you are thinking something like “I want to expose my local service to a public address” then ngrok is a great (free) tool that I like using. My current usage is exposing my local MySQL database service to the internet, so my public services can use its data.

I kick off ngrok on my local machine like this:

ngrok.exe tcp 3306

That starts up a local process that gives me a public address and port that I can connect to using my MVC.Net projects:

After running ngrok.exe, you should see something like the above. This shows TCP traffic at the public address 0.tcp.ngrok.io on port 123456 (actual value obfuscated) is routed to my localhost:3306, which is exactly where my local MySQL is listening.
Setup:

Head over to ngrok.com and create a free account, and download their ngrok.exe. Your free account has a secret key associated with it. The first time you run ngrok.exe you’ll need to set that key like this:

ngrok.exe authtoken <YOUR_AUTHTOKEN>

After that, you’re all set to spin up ngrok for exposing local services to the internet.

MVC.Net Connection String:

In order for your mvc.net connection string to hit the ngrok pubilc address, you’ll need to change the data source part of the connection string.

An example server and port for connecting to an exposed MySQL instance:

server=0.tcp.ngrok.io;Port=123456
An example data source for connecting to an exposed SQL Server:
data source=0.tcp.ngrok.io,55555

Notice the comma before the port number in the SQL Server connection string format.

In my experience, I only had to change data source or server/port. All of the other fields (user, password, timeouts, etc…) did not need any changes when switching to a ngrok publicly exposed database.

Other Uses:

I also use ngrok.com to expose my local ElasticSearch and some local IIS hosted websites for various (short term) demos and other purposes.

When you publish a website to local IIS, that will be serving over some port that you can configure. We’ll use 5555 for this example. You can expose that local IIS hosted website to the internet like this:

ngrok.exe http 5555

Or, a local ElasticSearch like this (with usually runs on localhost:9200):

ngrok.exe http 9200

Warning: ElasticSearch doesn’t have built in authentication, so wrapping that with an nginx locally is recommended. I do that with NovelEssay.com in that I’m hosting my website via GoDaddy and use an ElasticSearch in Azure with ngrok and nginx authentication.


Security Disclaimer:

Be careful with ngrok. Exposing your local ElasticSearch directly is not recommended, because ElasticSearch doesn’t have authentication built in. You can use things like nginx to create a basic authentication wrapper around ElasticSearch, and then expose the nginx service to the internet via ngrok. The same is with any other local service. Ngrok is awesome, but be careful.