Getting started with Alexa App development for Amazon Echo using .NET on Windows



Developing apps for Amazon Echo, called Alexa skills, is different than developing for other devices such as Android or iOS smartphones. Alexa skills are not installed on the actual device. Instead, they are web services hosted in the cloud. When a user wakes an Echo device and makes a request, that request is sent to the Alexa service in the cloud. If the request was intended for your app, the Alexa service sends a request to your app, waits for the response, and delivers the response to the user. You can develop the web service for your Alexa skills using any programming language as long as you respect the Alexa REST interface which uses JSON payloads over HTTPS.

That being said, there are toolkits for various languages and web service frameworks that make it easier to develop your app so you don't have to write the boilerplate code that parses request objects, verifies the authenticity of the requests and serializes the response. Because Amazon is primarily a Linux + Java shop their documentation prioritizes how to develop using that platform. So we wrote this guide for .NET developers and open sourced AlexaSkillsKit.NET to be your toolkit for .NET.

Set up your development environment

The Alexa service is strict regarding app endpoints. It will only call out using HTTPS on port 443 whether it's calling an app during development or deployed to production. This means you need to set up your development machine to accept incoming requests on port 443 which is not typical for a dev environment. Setup is further complicated because, as of this writing, the Alexa HTTPS client that makes the outbound calls to your app does not support SNI. So your app needs to be the HTTPS endpoint bound to the hosts' IP address (which effectively excludes a number of cloud hosting options for your app).

Irrespective of which web server you use on your dev machine (IIS, IIS Express, etc.) incoming HTTPS traffic on Windows is received by HTTP.SYS, a kernel-mode driver and a core part of the OS, which passes the request to the web server. To configure HTTP.SYS to accept requests on 443, from an elevated command prompt, run

netsh http add urlacl url=https://localhost:443/ user=Everyone

you also need to tell windows firewall to allow incoming traffic on port 443

netsh advfirewall firewall add rule name="HTTPS" dir=in action=allow protocol=TCP localport=443

In addition to receving HTTPS traffic you have to configure your development endpoint with an SSL certificate. Since Alexa service will validate this SSL certificate you either have to get one from an approved CA or generate your own and register the public key in the Amazon Developer Console. The command to generate your own cert is

makecert -r -pe -n "CN=localhost" -b 01/01/2000 -e 01/01/2036 -eku 1.3.6.1.5.5.7.3.1 -ss my -sr localMachine -sky exchange -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12

Whether you purchased a certificate from a CA or generated your own, you need to tell HTTP.SYS which SSL certificate you want to use for your development endpoint so, from an elevated command prompt, run:

netsh http add sslcert ipport=0.0.0.0:443 appid={00112233-4455-6677-8899-AABBCCDDEEFF} certhash=[certificate hash]

To get the [certificate hash] you need to find the certificate in the Certificate Manager. Run MMC.exe, go to File | Add/Remove Snap In, then select Certificates. Pick the Computer Account and look under Personal Certificates. Double click on your certificate (you can differentiate by expiration date if you see multiple). Go to Details, and scroll down to Thumbprint. Copy and paste into Notepad so you can remove the inner spaces before pasting it on the command line. If you haven't worked with SSL certificates before this article is a good primer.

If you go the route of generating your own cert Amazon requires that you submit its public key in the Amazon Developer Console where you register your Alexa app, so Alexa service can validate it. Alexa needs the public key in a Base 64 format called PEM in Linux and MacOS but which Windows refers to as Base 64 encoded CER format. To get your cert in this format Run MMC.exe, go to File | Add/Remove Snap In, then select Certificates. Pick the Computer Account and look under Personal Certificates. Right click your certificate and choose Export. In the Export wizard choose "No, do not export the private key" and then "Base 64 encoded X.509 (.CER)".

Take the content of the resulting file and paste it in the Amazon Developer Console under your app's registration, including the BEGIN/END CERTIFICATE markers

When you're done with developing your Alexa app you can undo all this with:

netsh http delete sslcert ipport=0.0.0.0:443
netsh http delete urlacl url=https://localhost:443/

It's outside the scope of this guide, but you have to get HTTPS inbound traffic from the edge of your network to your dev machine. If you're working in a small office or at home this means configuring your broadband modem to send traffic coming in on 443 to your dev machine. If you're in larger office with formal corporate network you have to work with your network admin to set up your dev machine as host in the DMZ and it that's forbidden by policy you have to do development on a rented VM in the cloud.

Start developing

You can use any number of web service frameworks to write your app, like ASP.NET Web API or ServiceStack. Irrespective of framework, the AlexaAppKit.NET toolkit makes it easy to write your app because it

  • parses the request into an easy to use object model
  • verifies authenticity of the request by validating its signature and timestamp
  • performs automatic session and conversation managements so you can easily write conversational apps

Here are the high level steps:

1. Implement ISpeechletAsync or ISpeechlet in a class that represents your app

public interface ISpeechletAsync
{
    Task<SpeechletResponse> OnIntentAsync(IntentRequest intentRequest, Session session);
    Task<SpeechletResponse> OnLaunchAsync(LaunchRequest launchRequest, Session session);
    Task OnSessionStartedAsync(SessionStartedRequest sessionStartedRequest, Session session);
    Task OnSessionEndedAsync(SessionEndedRequest sessionEndedRequest, Session session);
}

(I recommend ISpeechletAsync if your app does makes requests to other cloud services)

public interface ISpeechlet
{
    SpeechletResponse OnIntent(IntentRequest intentRequest, Session session);
    SpeechletResponse OnLaunch(LaunchRequest launchRequest, Session session);
    void OnSessionStarted(SessionStartedRequest sessionStartedRequest, Session session);
    void OnSessionEnded(SessionEndedRequest sessionEndedRequest, Session session);
}

2. Route requests from the web server hosting environment to your class

For example, if you're using ASP.NET Web API you write a small wrapper API method:

public class AlexaController : ApiController
{
    [Route("my-app-endpoint")]
    [HttpPost]
    public async Task<HttpResponseMessage> MyAppEndpoint() {
        var speechlet = new MySpeechlet();
        return await speechlet.GetResponseAsync(Request);
    }
}

3. Develop, Test, Debug; Lather, Rinse, Repeat

If you need to see the raw request and response you can attach a debugger because AlexAppKit.NET will output the headers and body to the debugger output. DO NOT use Fiddler as a reverse proxy to inspect traffic from Alexa. Not because Fiddler isn't a good tool for that, but because when Fiddler acts a reverse proxy, it's an open proxy and you'll become a vector for malware. I know this from experience. It took 24h after I opened port 443 to my machine, until I started getting traffic from malware command and control nodes and from what looked like Tor exit nodes.