Debugging BotFramework locally using ngrok

No doubt you’re already having lovely long conversations with your bot via Skype (or Facebook Messenger, or even SMS!) built using the botframework, and by using the Bot Emulator you can run your bot locally and debug it.

However, once it’s deployed and is being called via the Bot Connector framework, instead of directly, things get a bit tougher.

If you haven’t managed to override the – rather nasty – default exception handling that swallows exceptions and spews out reams of useless stack trace, then you may not have much idea what’s going on with your deployed bot, since all you get back is “Sorry, my bot code is having a problem.”

When you encounter a strange problem whilst conversing with your bot in Skype, going through the process of adding loads of logging and redeploying, trying again, checking logs – just to see the journey your bot code is going through – isn’t the most efficient.

If only you could debug the code on your development PC just as easily as you could before the bot was deployed, locally in Visual Studio…

In this article I’m going to show you how to debug your bot code from Skype though to your local PC’s Visual Studio instance, thanks to the amazing ngrok!

Ngrok

Ngrok is a small executable that creates secure tunnels to localhost. What does that actually mean? It means that ngrok can create a public HTTPS (And HTTP. And SSH) endpoint for any port on your local PC.

WOAH.

SO. CLEVER.

Go and download ngrok, then come back here. I’ll wait. It’s only a small zip.

Got it? Awesome, now extract the executable somewhere handy, perhaps a directory that’s already in your PATH.

Done that? Ok, let’s get started!

Using ngrok

There are a plethora of configuration options for ngrok, but we’re going to concentrate on the ones that allow localhost to be exposed externally and map the incoming request back to Visual Studio.

First up – Visual Studio

Open Visual Studio, get your bot code loaded and hit F5. You’ll be presented with a screen like this:

Running a bot project in VS

That’s the port we’re interested in. Write it down. Or just remember it. Whatever works for you

Secondly – ngrok

Now open up a command prompt of your choice and (unless you extracted ngrok somewhere that’s already in your PATH or you added it to your PATH) navigate to the location of your ngrok executable.

All you need to do now is enter this:

ngrok.exe http 3979 -host-header="localhost:3979"

This is exposing the port 3979 over HTTP and mapping incoming connections with the host header “localhost:3979” so that IIS Express picks them up; without this -host-header param the incoming connections will just fail.

Hit [Enter], and be patient. It’s doing EXTREME MAGIC in the background, which naturally takes a few seconds. After a short break you should end up with something like this:

ngrok initial view

The foundations have been laid! Pay attention to that “Web Interface” URL, since we’ll use that later on!

Third – botframework dev portal

Now we need to register our bot in the portal so we can get the App ID and App Key/Secret/Password. Head on over to https://dev.botframework.com/bots/new, log in with your Microsoft Live (or whatever they’re calling it this month) account, and you’ll see something like this:

dev portal registration

Under “Configuration” you’ll see “Messaging Endpoint”: paste your HTTPS ngrok URL in here, adding “/api/messages” at the end.

Then click the “Create Microsoft AppID and password” to open a new page where you specify the app name and are given an App Id . Now click “Generate a password to continue” – take these two values and paste them in your bot’s web.config:

<appSettings>
  <!-- update these with your BotId, Microsoft App Id and your Microsoft App Password-->
 <add key="BotId" value="PUT YOUR BOT HANDLE IN HERE" />
 <add key="MicrosoftAppId" value="PUT YOUR APP ID IN HERE" />
 <add key="MicrosoftAppPassword" value="PUT YOUR PASSWORD IN HERE" />
</appSettings>

Save this file – which will cuase your debug session to stop – and rerun your bot; don’t worry about ngrok as the URL will stay the same unless you restart ngrok itself. Which you should avoid doing, since this is the URL you’re registering with the portal.

Complete the rest of the form in the portal and hit “Register”.

You should now see the bot dashboard where you can enable or disable the various integrations; Skype should already be enabled by default.

Finally – debug!

Let’s set a breakpoint in your MessagesController in the Post method. Now go back to your bot portal and click the “Add to Skype” button in the Skype channel; this should take you to a page with an “Add to Contacts” button – hit that, log in with your Skype details, and eventually you’ll be able to open up Skype and start a conversation with your locally hosted bot.

In Skype say “hi” to your bot; in the ngrok window you should see some traffic being logged. If you look at the previous ngrok screenshot you’ll see a URL for a “web interface” – I said to remember it! – so head over to that URL and you’ll even be able to inspect the structure of the requests coming in!

ngrok web interface request inspector

Absolutely magical. This is a fantastically powerful and simple tool for debugging and capturing traffic coming in to whatever process is being exposed on your local PC.

Eventually your breakpoint should be hit:

Visual Studio breakpoint

So long as you keep your ngrok process running, you should keep the same url; you can keep stopping and starting Visual Studio, however, as you make you changes and try debugging again.

Summary

In this article we’ve learned about using ngrok to expose your local PC over HTTPS with a public URL, register this with the botframework portal, and debug a Skype chat running your bot code locally.

Hope you found this useful!

Until next time…

Summing CSV data with Powershell

As I’ve mentioned previously, I tend to use Powershell for all manner of random things. This time around I wanted to use it to avoid having to upload a csv to google drive or opening up my other laptop that has Excel on it, just to get some numbers.

I’m self-employed, so I have to regularly do my personal tax return. My – extremely inefficient – process involves leaving it until the last minute, then trawling through my online bank account and downloading each month’s statement in csv format and digging through these to find the numbers I need to fill out the various documents.

Naturally, I’d prefer to do this automatically, ideally scripted. So I did!

Let’s assume you’ve got a CSV file called September.csv that you want to play with, perhaps with content a bit like this:

Date,Description,Amount
2016/09/13,Black Coffee,3
2016/09/12,Espresso,1.70
2016/09/11,Double Espresso,2
2016/09/10,Whiskey,8

Let’s read the csv file in as text:

Get-Content .\September.csv

Now let’s convert the content into a Powershell object by piping the file contents into another cmdlet:

Get-Content .\September.csv | ConvertFrom-Csv

Here’s where we can use the Measure-Object (or just measure) cmdlet to pull out various useful stats, such as Sum, Average, Maximum, and Minimum for a given property – which in this case maps to the “Amount” column in my csv file:

Get-Content .\September.csv | `
ConvertFrom-Csv | `
Measure-Object "Amount" -Average -Sum -Maximum -Minimum

This gives us the results:

Count    : 4
Average  : 3.675
Sum      : 14.7
Maximum  : 8
Minimum  : 1.7
Property : Amount

Awesome!

How about you want to filter that a bit? I want to know just how much I’ve spent on espressos, so I’m going to use Where-Object (where for short):

Get-Content .\September.csv | `
ConvertFrom-Csv | Where-Object {$_.Description.Contains("Espresso")} | `
Measure-Object "Amount" -Average -Sum -Maximum -Minimum

Which results in:

Count    : 2
Average  : 1.85
Sum      : 3.7
Maximum  : 2
Minimum  : 1.7
Property : Amount

Handy, huh? Another little one-liner to get you through the day.

Persisting data within a conversation with botframework’s dialogs

In the previous botframework article I covered the different types of responses available for the botframework. This article is going to touch on the Dialog and persisting information between subsequent messages.

So what’s a Dialog?

Dialogs can call child dialogs or send messages to a user. Dialogs are suspended when waiting for a message from the user to the bot. Dialogs are resumed when the bot receives a message from the user.

To create a Dialog, you must implement the IDialog<T> interface and make your dialog class serializable, something like this:

[Serializable]
public class HelloDialog : IDialog<object>
{
    protected int count = 1;

    public async Task StartAsync(IDialogContext context)
    {
        await context.PostAsync($"You're new!");
        context.Wait(MessageReceivedAsync);
    }

    public async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
    {
        var message = await argument;
        await context.PostAsync($"I've seen you {count++} times now, {message.From.Name}");
        context.Wait(MessageReceivedAsync);
    }
}

What I’m trying to show here is how the dialog handles an initial message from a new user, versus the continuation of a conversation with that same user.

In order to wire the dialog up to the MessagesController you need to reference Microsoft.Bot.Builder.Dialogs and use the Conversation.SendAsync() method:

public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
    if (activity.Type == ActivityTypes.Message)
    {
        // needs a reference to Microsoft.Bot.Builder.Dialogs
        await Conversation.SendAsync(activity, () => new HelloDialog());
    }
    else
    {
        HandleSystemMessage(activity);
    }
    var response = Request.CreateResponse(HttpStatusCode.OK);
    return response;
}

With this implemented you should see something similar to the following conversation if you use the bot framework channel emulator:

dialog with basic state

The magic is in context.Wait:

context wait tooltip

Suspend the current dialog until the user has sent a message to the bot

So what we’ve done here is implement IDialog<T>’s StartAsync method, then tell the bot to hang around, waiting for another message in the same conversation from the same user using context.Wait.

Well, that sounds like stateful communication, right? Which sucks, since it inhibits scaling by requiring sticky sessions.

A-ha! But not quite, in this case; in something that hopefully doesn’t end up looking like viewstate, we have DialogState encoded in the context’s PrivateConversationData’s Bag:

dialogstate in the context's privateconversationdata

This will allow state to be carried around and the conversation continued without the user needing to be tied to a single instance of the bot. Nice.

Let’s play with that a bit:

public async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
    int heresavalue = 1;
    if (!context.PrivateConversationData.TryGetValue<int>("countthingy", out heresavalue)) { heresavalue = 1; }

    var message = await argument;
    await context.PostAsync($"I've seen you {count++} times now, {message.From.Name} and also {heresavalue}");
    context.Wait(MessageReceivedAsync);

    context.PrivateConversationData.SetValue<int>("countthingy", heresavalue * 2);
}

Now we’re setting a variable heresavalue and doubling it for each message in the same conversation, just to show that the value is being persisted; after a few messages, it looks like this:

UDC in privateconversationdata

context.PrivateConversationData.SetValue<T> and context.PrivateConversationData.TryGetValue<T> mean we can push info into the databag and get it back again within the context of a one on one chat.

The same is also true for context.ConversationData, where the conversation is a group (i.e., the bot and more than one other user), instead of one-to-one.

Skype

What’s quite cool is how your Skype name is pulled out from message.From.Name when the bot is deployed to Skype

skype name being passed in the message

Summary

Hopefully this short article gave you an idea of how to implement a Dialog and how you can persist state within a conversation.

Rate-Limiting, Powershell, Pester, and the ZenDesk API

Have you ever had to utterly hammer an API via a little Powershell script, only to find you’re getting rate limited, and lose all that previously downloaded data before you could persist it somewhere?

I have. I’ve recently put together a script to query a customer support ticketing system’s API, get a list of all tickets within a given time period, then query again to get to get the full content for each ticket.

All of this data is being added to a custom Powershell object (as opposed to churning out to a file as I go) since I convert it all to Json right at the end.

I’d rather not get half way through a few thousand calls and then have the process fail due to being throttled, so I’ve chosen to create a little function that will check for – in my case – an HTTP 429 response (“Too Many Requests”), get the value of the “Retry-After” header, then wait that many seconds before trying again.

This particular implementation is all quite specific to the ZenDesk API, but could easily be adapted to other APIs which rate limit/throttle and return the appropriate headers.

I’ve called the function CalmlyCall as a nod to Twitter’s original throttling implementation when they used HTTP 420 – “Enhance Your Calm” – back in the day.

function CalmlyCall($uri, $headers) {
    $enhanceyourcalm = 0

    do {
        if ($enhanceyourcalm -gt 0) {
            Write-Host -Object "Throttled; calming down for $enhanceyourcalm seconds..."
            Start-Sleep -Seconds $enhanceyourcalm
            $headers.Calm = $true
        }

        $response = Invoke-WebRequest -Uri $uri -Headers $headers -UseBasicParsing
        $ratelimit = $response.Headers['X-Rate-Limit-Remaining']

        if ([int]$ratelimit -lt 50) {
            Write-Host -Object "Calm may be needed: rate limit remaining - $($ratelimit)"
        }

        $enhanceyourcalm = $response.Headers["Retry-After"]
    } while ($response.StatusCode -eq 429)

    return ConvertFrom-Json $response.Content
}

You’ll see that I’m just using a do .. while loop to call the specified endpoint, check the headers for throttling information, and patiently (using Start-Sleep) until I’m allowed to continue. Simple stuff.

I’m only adding a Calm header when I’m throttled to make it more easily testable. I’m sure there’s a better solution to this, but it works well enough for me.

And since I’m a fan of testing my powershell, here’s the associated Pester script – it’s not great, since I’m mocking against Write-Host, for example:

$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
. "$here\$sut"

Describe "CalmlyCall" {
    Context "if no rate limiting exists" {
        It "should call the endpoint" {
            Mock Write-Host {}
            Mock Invoke-WebRequest -ParameterFilter { $Uri.ToString().EndsWith("test.here") } {        
                [PSCustomObject] `
                @{
                    Headers = @{};
                    StatusCode = 200;
                    Content = "{'result':'mycontent'}"
                }
            }

            $actual = CalmlyCall -uri "test.here" -headers @{}

            Assert-MockCalled Invoke-WebRequest
            $actual.result | Should be "mycontent"
        }
    }


    Context "if rate limiting exists" {
        It "should check limit remaining" {
            Mock Invoke-WebRequest -ParameterFilter { $Uri.ToString().EndsWith("test.here") } {        
                [PSCustomObject] `
                @{
                    Headers = @{'X-Rate-Limit-Remaining' = '20';'Retry-After' = '0'};
                    StatusCode = 200;
                    Content = "{'result':'mycontent'}"
                }
            }

            Mock Write-Host -ParameterFilter { $Object.ToString().EndsWith("rate limit remaining - 20")}

            $actual = CalmlyCall -uri "test.here" -headers @{}

            Assert-MockCalled Invoke-WebRequest
            Assert-MockCalled Write-Host -Times 1 -Exactly
            $actual.result | Should be "mycontent"
        }
    }


    Context "if initial request is throttled" {
        It "should respect throttling" {
            Mock Invoke-WebRequest -ParameterFilter { $Uri.ToString().EndsWith("test.here") } {        
                [PSCustomObject] `
                @{
                    Headers = @{'X-Rate-Limit-Remaining' = '0';'Retry-After' = '10'};
                    StatusCode = 429;
                    Content = "{'result':'mycontent'}"
                }
            }

            Mock Invoke-WebRequest -ParameterFilter { $Uri.ToString().EndsWith("test.here") -and $Headers -ne $null -and $Headers.Calm} {        
                [PSCustomObject] `
                @{
                    Headers = @{'X-Rate-Limit-Remaining' = '100';'Retry-After' = '0'};
                    StatusCode = 200;
                    Content = "{'result':'mycontent'}"
                }
            }

            Mock Start-Sleep -ParameterFilter { $Seconds -eq 10 }
            Mock Write-Host -ParameterFilter { $Object.ToString().EndsWith("rate limit remaining - 0") -or
                                               $Object.ToString().StartsWith("Throttled; calming down for 10 seconds")}

            $actual = CalmlyCall -uri "test.here" -headers @{}

            Assert-MockCalled Invoke-WebRequest -Times 2 -Exactly
            Assert-MockCalled Start-Sleep -Times 1 -Exactly
            Assert-MockCalled Write-Host -Times 2 -Exactly
            $actual.result | Should be "mycontent"
        }
    }
}

Feel free to suggest improvements!

Botframework Web Chat Embedding

The past two articles have been about setting up a botframework bot in Skype and comparing the various Skype clients to see how it’s rendered. In this short article we’ll have a look at configuring the Web Chat client.

Web Chat client is enabled by default when you register your bot:
enabled clients

If you click “edit” next to Web Chat, you’re taken to the configuration page:

configure within botframework dev portal

Click “Regenerate Web Chat secret” and those textboxes will be populated
regenerate web chat secret

You can now embed the web chat client on your webpage using an iframe

<iframe src='https://webchat.botframework.com/embed/rposbo_demo_bot?s=YOUR_SECRET_HERE'></iframe>

Which looks like this – have a play!

Rich botframework conversation cards

In the last article about bots I covered creating a basic bot using Microsoft’s botframework, setting up Azure, deploying the bot into Azure, and configuring it to work within Skype.

In this article we’re going to investigate the various response types available to us in the botframework to develop a more rich conversational experience.

Markdown

Luckily you’re not limited to plain text in a bot conversation; we’re able to embed images, add attachments, give headers and subheaders, add a button or link, tap events for various areas, as well as use markdown to format the main text content.

If you’re not already familiar with Markdown, then get on the case! It means you can very easily write HTML by using a shorthand syntax which can easily be converted to HTML.

I’ve been using it for many years for blogging and general documentation; using pandoc you can even convert markdown to PDF or a Word Doc. Using remark.js or the more recent Marp you can use it to easily create PowerPoint-like presentations

markdown example

Botframework messages support using this syntax to make the responses more rich. Of course, for this to work, the attached service needs to know how to render the response (and I’ll get on to this later)

Response Types

If you go and read the first article in my botframework series, you’ll recognise this as the default reply logic within the boilerplate MessagesController:

// return our reply to the user
Activity reply = 
   activity.CreateReply($"You sent {activity.Text} which was {length} characters");

For each of the following response type examples just replace this line from the default MessagesController with the example code.

Let’s make an example response just using some basic markdown to give a heading (a single “#” at the start of a line is an “H1”, two “##” is an “H2”, etc), bold, italic, a link, an image, a blockquote, and a code block:

var markdownContent = "#A heading\n";
markdownContent += "##A subheading\n";
markdownContent += "**something bold**\n\n";
markdownContent += "*something italic*\n\n";
markdownContent += "[a link!](http://robinosborne.co.uk/?s=bot)\n\n";
markdownContent += "![AN IMAGE!](http://robinosborne.co.uk/wp-content/uploads/2016/07/robinosborne.jpg)\n";
markdownContent += "> A quote of something interesting\n\n";
markdownContent += "```\nvar this = \"code\";\n```\n";

Activity reply = activity.CreateReply(markdownContent);

Now here’s the the rub: as I mentioned at the start, in order to use these rich responses the service to which your bot is talking needs to know how to render the content. The JSON response will just contain a block of markdown, not a pre-rendered chunk of HTML for example. As such, the services (such as Skype or Slack) need to know how to render markdown.

The case in point; here is the above message being rendered in different services:

Markdown: in the Bot Channel Emulator

markdown response rendered in bot channel emulator

Alright, that’s pretty awesome! The H1 and H2 came out nicely, as did the bold and italic text. The image was embedded and the alt/title was even rendered underneath, but the image has been stretched to look much bigger than the original; and there’s the link. The blockquote looks great and there’s even a nicely formatted code block! Aces! This is great, right?..

Markdown: in the Skype Desktop App

markdown response in Skype desktop app

Uh, okayyy.. H1 and H2 are just underlined, bold and italic are good as is the link; the image isn’t embedded and the quote is certainly rendering as a quote, but needs a cite perhaps. The code block seems to have been ignored.

Markdown: in the Skype Web App

markdown response in Skype web app

The quote is ignored, and the image doesn’t even link to the image, like it did in the desktop app.

Markdown: in the Skype Android App

markdown response in Skype android app

Now we’ve got an embedded image (sort of), the quote just has an empty (null) cite and the code block is ignored.

Mixed Results for markdown rendering in Skype vs the emulator, for sure. And these all use the same JSON response:

"text": "#A heading\n##A subheading\n**something bold**\n\n*something italic*\n\n[a link!](http://robinosborne.co.uk/?s=bot)\n\n![AN IMAGE!](http://robinosborne.co.uk/wp-content/uploads/2016/07/robinosborne.jpg)\n> A quote of something interesting\n\n```\nvar this = \"code\";\n```\n"

Attachments

As well as plain old text and funky markdown messages, we can add simple media attachments – images, audio, video, or generic “files”

Let’s try to send a couple of images:

Activity reply = activity.CreateReply("Here's an **image attachment**");
reply.Attachments = new List<Attachment> {
   new Attachment()
   {
       ContentUrl = "http://robinosborne.co.uk/wp-content/uploads/2016/07/image-attachment-tachikoma.jpg",
       ContentType = "image/jpg",
       Name = "Tachikoma - jpg"
   },
   new Attachment()
   {
       ContentUrl = "http://robinosborne.co.uk/wp-content/uploads/2016/07/image-attachment-gypsy-danger.png",
       ContentType = "image/png",
       Name = "Gypsy Danger - png"
   }
};

Image Attachments: in the Emulator

image attachments response in bot channel emulator

Great stuff; that’s a jpg and a png with their alt appearing as a caption.

Image Attachments: in Skype Desktop

image attachments response in skype desktop

Image Attachments: in Skype Web App

image attachments response in skype web

Image Attachments: in Skype Android App

image attachments response in skype  android app

Some subtle differences there, but overall a pretty standard response.

Rich Attachments: Hero Card

As well as plain old media attachments, we can also attach “cards”. These cards can have some extra functionality, like buttons and tap events.

The hero card contains a single large image, a button, and a “tap action”, along with text content.

Activity reply = activity.CreateReply("Here's a **hero**");

var heroCard = new HeroCard()
{
    Title = "I'm a hero card",
    Subtitle = "Robin hearts Tachikoma",
    Images = new List<CardImage> {
        new CardImage(url: "http://robinosborne.co.uk/wp-content/uploads/2016/07/robinosborne.jpg")
    },
    Buttons = new List<CardAction> {
     new CardAction()
        {
            Value = "https://robinosborne.co.uk/?s=bot",
            Type = "openUrl",
            Title = "Rob's bots"
        } 
    }
};

reply.Attachments = new List<Attachment> {
    heroCard.ToAttachment()
};

Hero: in Emulator

hero attachments response in emulator

Awesome – like it said in the description; a heading, a button, and an image.

Hero: in Skype

botframework hero attachment in skype android app

Looking good

Rich Attachments: Thumbnail Card

The thumbnail card can have a single small image, a button, and a “tap action”, along with text content to display on the card.

Activity reply = activity.CreateReply("Here's a **thumbnail**");

var thumbnailCard = new ThumbnailCard()
{
    Title = "I'm a thumbnail card",
    Subtitle = "Tachikoma hearts Robin",
    Images = new List<CardImage> {
        new CardImage(url: "http://robinosborne.co.uk/wp-content/uploads/2016/07/image-attachment-tachikoma.jpg")
    },
    Buttons = new List<CardAction> {
     new CardAction()
        {
            Value = "https://robinosborne.co.uk/?s=bot",
            Type = "openUrl",
            Title = "Rob's bots"
        }
    }
};

reply.Attachments = new List<Attachment> {
    thumbnailCard.ToAttachment()
};

Thumbnail: in Emulator

thumbnail attachments response in emulator

Does as expected, but the text content doesn’t look perfect – the justified alignment is odd in the emulator. Maybe Skype can do better?…

Thumbnail: in Skype

botframework thumbnail attachment in skype android app

The Android app is looking nice.

Rich Attachments: Receipt Card

The concept of this is kinda cool; a card to – presumably – summarise a purchase, which implies it should be possible to complete a transaction all within the scope of a conversation.

The receipt card can contain a title, “facts”, line items, tax, VAT, total value, and one or more buttons. It’s a beefy one – are you ready?..

Activity reply = activity.CreateReply("Here's a **receipt**");
var receiptCard = new ReceiptCard()
{
    Title = "I'm a receipt card",
    Buttons = new List<CardAction> {
        new CardAction()
        {
            Value = "https://robinosborne.co.uk/?s=bot",
            Type = "openUrl",
            Title = "Pay with rposbo bucks",
            Image = "http://robinosborne.co.uk/wp-content/uploads/2016/07/robinosborne.jpg"
        },
        new CardAction()
        {
            Value = "https://robinosborne.co.uk/?s=bot",
            Type = "openUrl",
            Title = "Paypal"
        }
    },
    Facts = new List<Fact> {
        new Fact("You shopped at", "Epic Shop"),
        new Fact("We love you", "THIS MUCH")
    },
    Items = new List<ReceiptItem> {
        new ReceiptItem
        {
             Title = "Building Great Startup Teams",
             Image = new CardImage("https://images-na.ssl-images-amazon.com/images/I/41xkMlpjRuL._AC_SX60_CR,0,0,60,60_.jpg"),
             Price = "9.99",
             Quantity = "1",
             Subtitle = "A Guide to Attracting, Hiring, and Retaining Employees",
             Text = "Dean Hume"
        },
        new ReceiptItem
        {
             Title = "Fast ASP.NET Websites",
             Image = new CardImage("https://images-na.ssl-images-amazon.com/images/I/51S6zPA2TYL._AC_SX60_CR,0,0,60,60_.jpg"),
             Price = "20.99",
             Quantity = "1",
             Subtitle = "Practical, hands-on guidance to create faster, more efficient ASP.NET sites",
             Text = "Dean Hume"
        }
    },
    Total = "30.98",
    Tax = "9.68",
    Vat = "10"
};

reply.Attachments = new List<Attachment> {
    receiptCard.ToAttachment()
};

Receipt: in Emulator

receipt attachment response in emulator

Woah. Yeah, you can seriously pack a load of information into this one card. It even renders quite nicely in the emulator, except notice that it’s using the main receipt’s title for each line item instead of the item’s title, but the correct title per line item is returned in the JSON, so this is just an issue with the emulator.

Still cool though. Having multiple buttons is interesting, and being able to add an image to a button could be handy for, say, payment method logos.

Receipt: in Skype

botframework receipt attachment in skype android app

This is a really slick looking card.

Rich Attachments: Sign In Card

The sign in card may not look like much (and it doesn’t), but when the card action is set to the type of “signin”, it can initiate an oauth flow; the user can be made to leave the conversation to authenticate with a third party system.

Activity reply = activity.CreateReply("Here's a **signin**");

var signinCard = new SigninCard()
{
    Text = "Authorisation needed",    
    Buttons = new List<CardAction> {
     new CardAction()
        {
            Value = "https://robinosborne.co.uk/?s=bot",
            Type = "signin",
            Title = "Facebook OAuth",
            Image = "https://cdn1.iconfinder.com/data/icons/logotypes/32/square-facebook-128.png"
        },
     new CardAction()
        {
            Value = "https://robinosborne.co.uk/?s=bot",
            Type = "signin",
            Title = "Google",
            Image = "http://images.dailytech.com/nimage/G_is_For_Google_New_Logo_Thumb.png"
        }
    }
};

reply.Attachments = new List<Attachment> {
    signinCard.ToAttachment()
};

SignIn: in Emulator

sign in attachment response in emulator

Ha – the smiley isn’t on the message at all; this is just how the emulator is rendering a “sign in” card!

SignIn: in Skype

botframework signin attachment in skype android app

Very cute! It hasn’t taken my content, nor my custom buttons; looks like the “sign in” card may use default content only.

it’s possible to use the AttachmentLayout property to return a response containing several different rich content cards, and combine them into a carousel display; by default these are displayed as a list, as you can see from the image attachments screenshot.

Currently this only works for hero and thumbnail cards, and the emulator just renders a horizontal scrollbar which flips between each card (i.e., as opposed to a smooth scroll).

Summary

In this article I’ve shown you the various response types available to developers in the botframework with an example implementation for each type.

The possibilities for this are already numerous; you could implement a bot which could have a simple “conversation” with a user, create a carousel of products (hero/thumbnail) with click or tap actions which could add products to a cart (maybe..), give the user a receipt, and have them authenticate via a sign in card.

The concepts are there, and it’s certainly promising.

Have a play, let me know how you get on!

Create your first botframework bot in Azure!

At //Build 2016 Microsoft unleashed something known as the Bot Framework; a set of three products to help you build conversational bots and connect them with services, like Slack, Skype, and even Email and SMS.

The Bot Framework has a number of components including the Developer Portal, Bot Builder, and the Bot Directory:

  • Developer Portal is where you wire your bot up to existing services like Skype and Slack
  • Bot Directory is where you publish your bot to so that others can search for and connect it to their Skype and Slack
  • Bot Builder is what you use to implement a more complex and intelligent conversational flow, optionally leveraging the awesome power of some of the Microsoft Research’s Cognitive Services for language interpretation, image recognition, and much more.

In this article I’m going to take you through the process of creating, deploying, and configuring your own Skype bot.

Bots

As far as some people are concerned, “bots” are the new “apps”; before too long every company will have to offer their own bot for some reason or another.

Concept of conversational bots is not new; nerds of my age or similar will no doubt be aware of ELIZA, a conversational bot with no intelligence as such, just giving semi-canned responses to input such as a cheap psychotherapist might do. Great fun though.

This sort of bot paved the way for significantly more complex human language-based interaction, having possibly been the first computer to “pass” the Turing Test!

ChatOps

The term ChatOps has been credited to GitHub following them unleashing Hubot on the tech world; a conversational bot which allowed members of github to interrogate and even update their various systems without leaving their chatroom.

The benefits of this are numerous, such as avoiding a second class citizen “admin” web interface for “backoffice” tasks. These “admin” sites never get as much development and refactoring time as your core product might, falling behind and eventually becoming a hindrance to the team.

Another key feature is the log of the conversation between the team and the bot, allowing for a simple audit log should the conversation include deployment or outage investigations.

Hubot

hubot

Hubot is a nodejs project from GitHub – open source, naturally – with coffeescript (“a little language that compiles into JavaScript”) “commands”, making it extremely simple to extend with your own commands.

I’ve previously deployed a hubot instance (called MrBot..) to heroku, with coffeescript commands to hook into a TeamCity instance’s API to trigger and report on builds and kick off deployments to Azure, through to querying an API in Azure to inspect diagnostic logs and report on system performance.

Being able to implement this all within the context of a conversation in hipchat or Slack was extremely natural and gave a cohesive experience.

botframework

This brings me back to the newly unleashed botframework. Now it’s even easier than ever to create your own conversational bot, deploy it, and connect it to various services.

So that’s what we’re going to do. Get comfy.

Install prerequisite software

In order to use the botframework you’re going to need to make sure you’re running an up to date Visual Studio with all the latest bells and whistles:

  • Visual Studio 2015 Update 3 (if you use Community edition, like me, you may find the Update 3 download actually tries to install Update 2; instead, just go to “Add or Remove Programs”, select Visual Studio > Modify and you’ll be able to install Update 3 from there)
  • Update all VS extensions to their latest versions:
    • Open Visual Studio > Tools > Extensions and Updates > Updates > the lot.
  • Download and install the Bot Application template; this gives you a new project type in Visual Studio:
    • http://aka.ms/bf-bc-vstemplate
    • Save the zip file to your VS templates directory, usually something like: “%USERPROFILE%\Documents\Visual Studio 2015\Templates\ProjectTemplates\Visual C#\”

Create your first bot

Exciting stuff, eh?

  • Open Visual Studio
  • Make sure you have “Create new git repository” selected, since we’ll be deploying to Azure using git
  • Create a new C# project using the new Bot Application template:

bot framework visual studio new project

Take a moment to check out what’s been created in Visual Studio from that new project template. There’s very little code; just a few config files, a mainly blank default.htm page, and a MessagesController class with an interesting using at the top:

using Microsoft.Bot.Connector;

And a nice auth attribute on the controller class:

[BotAuthentication]

Inside that MessagesController class is an interesting method:

public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
    if (activity.Type == ActivityTypes.Message)
    {
        ConnectorClient connector = 
            new ConnectorClient(new Uri(activity.ServiceUrl));

        // calculate something for us to return
        int length = (activity.Text ?? string.Empty).Length;

        // return our reply to the user
        Activity reply = 
            activity.CreateReply($"You sent {activity.Text} which was {length} characters");
        await connector.Conversations.ReplyToActivityAsync(reply);
    }
    else
    {
        HandleSystemMessage(activity);
    }
    var response = Request.CreateResponse(HttpStatusCode.OK);
    return response;
}

The ServiceUrl is the system that’s currently calling the bot endpoint; e.g., Skype or Slack.

Other than that, it’s pretty sparse:

vs new bot framework project

So we’ve created a .Net Web API with some special authorisation implementation, and an endpoint to which all messages (Activitys) are sent.

There are various activity Types, for events such as your bot or another user joining or leaving a conversation, your bot or another user joining or leaving a group conversation (all of which are grouped under the ActivityTypes.ConversationUpdate type, the bot being added to or removed from a user’s contacts list (ActivityTypes.ContactRelationUpdate), knowing that the user is typing (ActivityTypes.Typing – now come on; this is cool!), and a couple of others.

This is where we’ll do all our cleverness; we’ll implement some message parsing logic in a new class and call it in here – we could even have this call a completely different API, using the “bot” merely as a basic web host with authorisation, and single entry point; we could potentially deploy this bot only once and leave it alone.

The botframework SDK allows for some complex conversation models, and I’ll go into this in another article.

Let’s come back to this concept shortly. First up, I’m going to show how to run, test, deploy, and connect to services. Which is really cool.

Locally running and debugging

You’re still in Visual Studio, so let’s hit F5 to run and debug:

Run and debug the bot framework in Visual Studio

Bot Framework Channel Emulator

It’s easy to test this endpoint by using the Bot Framework Channel Emulator; a simple “Click Once” application from Microsoft. Since it’s a Click Once app, it will auto update when necessary. Very handy.

Once your bot/web api is running locally, open up the Bot Framework Emulator, and enter the following details:

  1. Bot Url: this will be localhost:<port>/api/messages – just grab the port from the browser window you launched when F5-ing the project
  2. Microsoft App Id: when testing locally, leave this blank; when testing a remote endpoint, use the Mirosoft App Id you’re given (we’ll get on to this shortly)
  3. Microsoft App Password: same as above; leave blank for local testing, or use the value you’re given from your bot dashboard (later)

If you’ve not made any code changes to the default project you should be able to type in a message at the box at bottom of the emulator and see a response letting you know the length of the message you just entered, along with the JSON for that response in the window on the right of the emulator.

testing locally with the bot emulator

Notice the full JSON response in the right side window; lots of interesting data in there…

Deploying to Azure

Now that we’ve got a “working” bot, it’s time to set it free into the big wide world so we can connect it to other services and start to see the real potential; once this step is done, updating with new functionality will be extremely easy.

The tutorial on the botframework website shows you how to use Visual Studio’s “Publish” functionality to deploy to Azure; I really don’t like this since it’s not supporting anything other than a single developer, with no support for collaboration and no “gates” to deployment – i.e., automated tests.

I’m going to implement a basic separation of these concerns (which I’ll expand on in a subsequent article by introducing a CI server to run tests before allowing us to deploy) using git.

git commit -am “It’s ALIVE!”

I love git. Git git git yum yum yum in my tum. Or something. So I’m going to use this as the deployment initialisation mechanism.

Given .Net Core runs on pretty much OS these days, we could deploy this anywhere; however, the bot requires HTTPS – as any web-based system should – and Azure gives this to you for free (unlike Appharbor, for example), so that’s my host of choice.

Aside: if you try to run your bot over HTTP from a remote endpoint you’ll get an error:

bot running over http gives a warning

Set up Azure

Create the new web app/app service (same thing)

  1. Go to portal.azure.com
  2. If you don’t already have an account, create one; I’ll not go into the detail of doing that here
  3. Select “New Web App” and click “Create”:
    Azure new web app

Configure deployment from git

  1. Once that’s finished creating it, select “Deployment Source” (under Settings > Publishing > Deployment Source) and choose “local git”
  2. Once that’s done, go to the “Essentials” view of your web app, get the git repo endpoint, and set a password for your deployment user (if you haven’t already)
  3. Set up a new git remote either from within Visual Studio’s Team Explorer window, or the command prompt, like:
    • git remote add azure <paste in your azure git repo url here>
    • git push azure master
    • Enter the deployment user’s password and away you go:
remote:   Copying all files to temporary location below for package/publish:
remote:   D:\local\Temp\8d3a8421b0c42a4.
remote: KuduSync.NET from: 'D:\local\Temp\8d3a8421b0c42a4' to: 'D:\home\site\wwwroot'
remote: Copying file: 'Web.config'
remote: Finished successfully.
remote: Running post deployment command(s)...
remote: Deployment successful.
To https:[email protected]:443/rposbo-botframework-demobot.git
   e16b753..9dac446  master -> master

Notice how the git push command is reporting on the actual deployment into Azure? How cool is that?

Testing in Azure
You can’t! At least, you can’t yet. We currently don’t have a valid MicrosoftAppId and MicrosoftAppPassword, remember? They’re still blank in our web.config! Before we can actually use this remotely deployed bot we need to get some valid credentials by registering it with the Microsoft Bot Framework.

Registering with the Microsoft Bot Framework

Head over to https://dev.botframework.com/, click Register a Bot.

Fill in a name and a “bot handle” – this will be your BotId in your web.config – and paste in your Azure endpoint + “/api/messages/” for the “Messaging endpoint” section.

Then click “Create Microsoft App ID and Password” to open up a new tab and log in with your Microsoft (Live/whatever it’s called now) details to see your already configured apps.

Click “Add an app”, give it a name, and on the next screen you’ll see your Microsoft App ID; paste this back in the bot registration page AND in your web.config as the MicrosoftAppId.

Click “Generate new password” and paste this in your web.config as the MicrosoftAppPassword

Finish the rest of this form, click “Register” and whilst you’re waiting for that to finish you can git push your new web.config up to Azure – make sure you’ve filled in your BotId, MicrosoftAppId, and MicrosoftAppPassword! Go on then.. get git pushing!

Say hello to your new friend!

You should now be back in your dev portal with your new bot listed and showing as already being connected to Skype!

Click that “Add to Skype” link..

And have a “chat”:

When you send your first message it may take a few seconds to get a response, but subsequent ones should be quicker.

You just had a chat with your very own Skype Conversational Bot! How cool is that?

Summary

Where do we go from here? You could connect your bot to other services if you have the prerequisites for that service, such as Facebook Messenger, SMS (Twilio) or Slack.

You could start to develop cleverness around parsing the content of the message, and responding appropriately.

You could investigate the various types of responses that are available, such as:

  • attachment – have an inline file or image with your message
  • hero – a “card” with header, subheader, image, and button
  • thumbnail – like a hero, but the image is smaller and to one side
  • receipt – a product listing with images, descriptions, and prices, with a subtotal and total!

You could check out carousels of response cards and combine everything into one giant reply!

Pretty cool, right? Have a go and let me know how you get along.

Unit Testing Powershell with Pester

I write a lot of Powershell these days; it’s my go-to language for quick jobs that need to interact with external systems, like an API, a DB, or the file system for example.

Nothing to configure, nothing to deploy, nothing to set up really; just hack a script together and run it. Perfect for one-off little tasks.

I’ve used it for all manner of things in my career so far, most notably for Azure automation back before Azure had decent automation in place. We’re talking pre-Resource Manager environment creation stuff.

I would tie together a suite of separate scripts which would individually:

  • create a Storage account,
  • get the key for the Storage account,
  • create a DB instance,
  • execute a DB initialisation script,
  • create a Service Bus,
  • execute a Service Bus initialisation script,
  • deploy Cloud Services,
  • start/stop/restart those services

Tie that lot together and I could spin up an entire environment easily.

powershell_azure_createdb

Continue reading

Save 24% With The Last Frontier of Minification: HTML!

As a web developer, front end developer, or web performance enthusiast (or all of those), it’s likely that you’re already minifying your JavaScript (or uglifying it) and most likely your css too.

Why do we do this?

We minify specifically to reduce the bytes going over the wire; trying to get our websites as tiny as possible in order to shoot them through the internet faster than our competitor’s.

We obsess over optimising our images, carefully choosing the appropriate format and tweaking the quality percentage, hoping to achieve the balance between clarity and file size.

So we have teeny tiny JavaScript; we have clean, minified, uncssed css; we have perfectly small images (being lazy loaded, no doubt).

So what’s left?…

The ever-overlooked … HTML minification!

Thats right! HTML! BOOM!

Seriously though; HTML may be the one remaining frontier for optimisation. If you’ve covered off all the other static files – the css, js, and images – then not optimising html seems like a wasted opportunity.

If you view the source of most websites you visit you’ll probably find line after line of white space, acres of indents, reams of padding, novels in the forms of comments.

Every single one of these is a wasted opportunity to save bytes; to squeeze the last few bits out of your HTTP response, turning it from a hulking oil tanker into a zippy land speeder.

Continue reading

Getting Browser Location in Chrome and Deprecating Powerful Features on Insecure Origins

A while ago I created the most useful web page I’ve ever written; an extremely basic page to list the bus arrival times, based on your current location anywhere in London!

I have used this page several times a day on an almost daily basis since I created it, as does my wife; every morning we need to know when the next bus will arrive near our house in order to know when to rush out with our children to take them to school.

I used it every morning to check if I needed to rush out the door to catch the rare “express” bus that would get me to the tube much quicker than the usual one.

I discovered just how useful it is whilst in a pub, deciding whether I had time for another drink before heading home; a quick glance at my phone and I could find out that the next bus home wasn’t for 20 minutes – plenty of time!

However, recently it stopped working for me. It still worked just fine on my wife’s iPhone (and hence Safari), but not on my Nexus (Chrome). It works on my laptop too, or at least appeared to.

So what’s going on?

Continue reading