×

First time here?

You are looking at the most recent posts. You may also want to check out older archives. Please leave a comment, ask a question and consider subscribing to the latest posts via RSS or email. Thank you for visiting!

After a sick day a few weeks ago and writing my first Alexa Skill I’ve been pretty engaged with understanding this voice UI world with Amazon Echo, Google Home and others.  It’s pretty fun to use and as ‘new tech’ it is pretty fun to play around with.  Almost immediately after my skill was certified, I saw this come across my Twitter stream:

I had spent a few days getting up-to-speed on Node and the environment (I’ve been working in client technologies for a long while remember) and using VS Code, which was fun.  But using C# would have been more efficient for me (or so I thought).  AWS Lambda services just announced they will support C# as the authoring environment for a Lambda service.  As it turns out, the C# Lambda support is pretty general so there is not compatibility in the dev experience for creating a C# Lambda backing a skill as there presently is for Node.JS development…at least right now.  I thought it would be fun to try and was eventually successful, so hopefully this post finds others trying as well.  Here’s what I’ve learned in the < 4 hours (I time-boxed myself for this exercise) spent trying to get it to work.  If there is something obvious I missed to make this simpler, please comment!

The Tools

You will first need a set of tools.  Here was my list:

With these I was ready to go.  The AWS Toolkit is the key here as it provides a lot of VS integration that will help make this a lot easier.

NOTE: You can do all of this technically with VS Code (even on a Mac) but I think the AWS Toolkit for VS makes this a lot simpler to initially understand the pieces and WAY simpler in the publishing step to the AWS Lambda service itself.  If there is a VS Code plugin model, that would be great, but I didn’t find one that did the same things here.

Armed with these tools, here is what I did…

Creating the Lambda project

First, create a new project in VS, using the AWS Lambda template:

This project name doesn’t need to map to your service/function names but it is one of the parameters you will set for the Lambda configuration, so while it doesn’t entirely matter, maybe naming it something that makes sense would help.  We’re just going to demonstrate a dumb Alexa skill for addition so I’m calling it NumberFunctions.

NOTE: This post isn’t covering the concepts of an Alexa skill, merely the ability to use C# to create your logic for the skill if you choose to use AWS Lambda services.  You can, of course, use your own web server, web service, or whatever hosted on whatever server you’d like and an Alexa skill can use that as well. 

Once we have that created you may see the VS project complain a bit.  Right click on the project and choose to restore NuGet packages and that should clear it up.

Create the function handler

The next step is to write the function handler for your skill.  The namespace and public function name matter as these are also inputs to the configuration so be smart about them.  For me, I’m just using the default namespace, class and function name that the template provided.  The next step is to gather the input from the Alexa skill request.  Now a Lambda service can be a function for anything…it is NOT limited to serve Alexa responses, it can do a lot more.  But this is focused on Alexa skills so that is why I’m referring to this specific input.  Alexa requests will come in the form of a JSON payload with a specific format.  Right now if you accept the default signature of the function handler of string, ILambdaContext it will likely fail due to issues you can read about here on GitHub.  So the best way is to really understand that the request will come in with three main JSON properties: request, version, and session.  Having an object with those properties exposed will help…especially if you have an object that understands how to automatically map the JSON payload to a C# object…after all that’s one of the main benefits of using C# is more strongly-typed development you may be used to.

Rather than create my own, I went on the hunt for some options.  There doesn’t exist yet an Alexa Skills SDK for .NET yet (perhaps that is coming) but there are two options I found.  The first seemed a bit more setup/understanding and I haven’t dug deep into it yet, but might be viable.  For me, I just wanted to basically deserialize/serialize the payload into known Alexa types.  For this I found an Open Source project called Slight.Alexa.  This was build for the full .NET Framework and won’t work with the Lambda service until it was ported to .NET Core, so I forked it and moved code to shared and created a .NET Core version of the library. 

NOTE: The port of the library was fairly straight forward sans for a few project.json things (which will be going away) as well as finding some replacements for things that aren’t in .NET Core like System.ComponentModel.DataAnnotations.  Luckily there were replacements that made this simple.

With my fork in place I made a quick beta NuGet package of my .NET Core version so I could use it in my Lambda service (.NET Core projects can’t reference DLLs so they need to be in NuGet packages).  You can get my beta package of this library by adding a reference to it via your new Lambda project:

This now gives me a strongly-typed OM against the Alexa request/response payloads.  You’ll also want to add a NuGet reference to the JSON.NET library (isn’t every project using this now…shouldn’t it be the default reference for any .NET project???!!!).  With these both in place now you have what it takes to process.  The requests for Alexa come in as Launch, Intent and Session requests primarily (again I’m over-simplifying here but for our purposes these are the ones we will look at).  The launch request is when someone just launches your skill via the ‘Alexa, open <skill name>’ command.  We’ll handle that and just tell the user what our simple skill does.  Do do this, we change the function handler input from string to SkillRequest from our newly-added Slight.Alexa.Core library we added:

public string FunctionHandler(SkillRequest input, ILambdaContext context)

Because SkillRequest is an annotated type the library knows how to map the JSON payload to the object model from the library.  We can now work in C# against the object model rather than worry about any JSON path parsing.

Working with the Alexa request/response

Now that we have the SkillRequest object, we can examine the data to understand how our skill should respond.  We can do this by looking at the request type.  Alexa skills have a few request types that we’ll want to look at.  Specifically for us we want to handle the LaunchRequest and IntentRequest types.  So we can examine the type and let’s first handle the LaunchRequest:

Response response;
IOutputSpeech innerResponse = null;
var log = context.Logger;

if (input.GetRequestType() == typeof(Slight.Alexa.Framework.Models.Requests.RequestTypes.ILaunchRequest))
{
    // default launch request, let's just let them know what you can do
    log.LogLine($"Default LaunchRequest made");

    innerResponse = new PlainTextOutputSpeech();
    (innerResponse as PlainTextOutputSpeech).Text = "Welcome to number functions.  You can ask us to add numbers!";
}

You can see that I’m just looking at the type and if a LaunchRequest, then I’m starting to provide my response, which is going to be a simple plain-text speech response (with Alexa you can use SSML for speech synthesis, but we don’t need that right now).  If the request is an IntentRequest, then I first want to get out my parameters from the slots and then execute my intent function (which in this case is adding the parameters):

else if (input.GetRequestType() == typeof(Slight.Alexa.Framework.Models.Requests.RequestTypes.IIntentRequest))
{
    // intent request, process the intent
    log.LogLine($"Intent Requested {input.Request.Intent.Name}");

    // AddNumbersIntent
    // get the slots
    var n1 = Convert.ToDouble(input.Request.Intent.Slots["firstnum"].Value);
    var n2 = Convert.ToDouble(input.Request.Intent.Slots["secondnum"].Value);

    double result = n1 + n2;

    innerResponse = new PlainTextOutputSpeech();
    (innerResponse as PlainTextOutputSpeech).Text = $"The result is {result.ToString()}.";

}

With these in place I can now create my response object (to provide session management, etc.) and add my actual response payload, using JSON.NET to serialize it into the correct format.  Again, the Slight.Alexa library does this for us via that annotations it has on the object model.  Please note this sample code is not robust, handles zero errors, etc…you know, the standard ‘works on my machine’ warranty applies here.:

response = new Response();
response.ShouldEndSession = true;
response.OutputSpeech = innerResponse;
SkillResponse skillResponse = new SkillResponse();
skillResponse.Response = response;
skillResponse.Version = "1.0";

return skillResponse;

I’ve now completed my function, let’s upload it to AWS!

Publishing the Lambda Function

Using the AWS Toolkit for Visual Studio this process is dead simple.  You’ll first have to make sure the toolkit is configured with your AWS account credentials which are explained here in the Specifying Credentials information.  Right click on your project and choose Publish to AWS Lambda:

You’ll then be met with a dialog that you need to choose some options.  Luckily it should be pretty self-explanatory:

You’ll want to make sure you choose a region that has the Alexa Skill trigger enabled.  I don’t know how they determine this but the US-Oregon one does NOT have that enabled, so I’ve been using US-Virginia and that enables me just fine.  The next screen will ask you to specify the user role (I am using the basic execution role).  If you don’t know what these are, re-review the Alexa skills SDK documentation with Lambda to get started there.  These are basically IAM roles in AWS that you have to choose.  After that you click Upload and done.  The toolkit takes care of bundling all your stuff up into a zip, creating the function (if you didn’t already have one – as if you did you can choose it from the drop-down to update an existing one) and uploading it for you.  You can do all this manually, but the toolkit really, really makes this simple.

Testing the function

After you publish you’ll get popped the test window basically:

This allows you to manually test your lambda.  In the pre-configured requests objects you can see a few Alexa request object specified there.  None of them will be the exact one you need but you can start with one and manually modify it easily to do a quick test.  If you notice my screenshot I modified to specify our payload…you can see the payload I’m sending here:

{
  "session": {
    "new": false,
    "sessionId": "session1234",
    "attributes": {},
    "user": {
      "userId": null
    },
    "application": {
      "applicationId": "amzn1.echo-sdk-ams.app.[unique-value-here]"
    }
  },
  "version": "1.0",
  "request": {
    "intent": {
      "slots": {
        "firstnum": {
          "name": "firstnum",
          "value": "3"
        }, "secondnum" : { "name": "secondnum", "value": "5" }
      },
      "name": "AddIntent"
    },
    "type": "IntentRequest",
    "requestId": "request5678"
  }
}

That is sending an IntentRequest with two parameters and you can see the response functioned correctly!  Yay!

Of course the better way is to use Alexa to test it so you’ll need a skill to do that.  Again, this post isn’t about how to do that, but once you have the skill you will have a test console that you can point to your AWS Lambda function.  I’ve got a test skill and will point it to my Lambda instance:

UPDATE: Previously this wasn’t working but thanks to user @jpkbst in the Alexa Slack channel he pointed out my issue.  All code above updated to reflect working version.

Well I had you reading this far at least.  As you can see the port of the Slight.Alexa library doesn’t seem to quite be working with the response object.  I can’t pinpoint why the Alexa test console feels the response is valid as the schema looks correct for the response object.  Can you spot the issue in the code above?  If so, please comment (or better yet, fix it in my sample code).

Summary (thus far)

I set out to spend a minimal amount of time getting the C# Lambda service + Alexa skill working.  I’ve uploaded the full solution to a GitHub repository: timheuer/alexa-csharp-lambda-sample for you to take a look at.  I’m hopeful that this is simple and we can start using C# more for Alexa skills.  I think we’ll likely see some Alexa Skills SDK for .NET popping up elsewhere as well. 

Hope this helps!


12/13/2016 1:57 AM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
Thanks for this Tim. I just went through the same experience as you, writing a skill in Python (which I've not used much before) to take notes in Evernote or OneNote. Good to see the steps involved in writing a skill in C#, which is also my preferred languag. One small thing I noticed is that you are allocating the response twice in the code snippet in "Working with the Alexa request/response".

Damian
12/13/2016 6:57 AM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
Thanks @damian -- the double alloc is a copy/paste error in the post only :-) -- thanks for pointing it out.
12/23/2016 5:42 AM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
Thanks for this guide. I did run into one problem and found one simplification that seemed to solve it. The return json was being double encoded after it was returned. I believe by the Amazon.Lambda.Serialization after it left the function.

I found that I could just modify the method signature to be

public SkillResponse FunctionHandler(SkillRequest input, ILambdaContext context)

Then I just returned the SkillResponse without using JsonConvert, and everything worked.
12/25/2016 12:19 PM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
Great work here. I am having an issue though...

Severity Code Description Project File Line Suppression State
Error CS0029 Cannot implicitly convert type 'Slight.Alexa.Framework.Models.Responses.SkillResponse' to 'string' NumberFunctions..NETCoreApp,Version=v1.0 C:\Users\Mike\Desktop\alexa-csharp-lambda-sample-master\NumberFunctions\Function.cs 58 Active

if i change to public SkillResponse FunctionHandler(SkillRequest input, ILambdaContext context) as i see in comments, it works in lambda but not with Alexa, Invalid response. What gives? Is it because the Attributes are null?
12/26/2016 5:58 AM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
if i change to public SkillResponse FunctionHandler(SkillRequest input, ILambdaContext context) as i see in comments, it works in lambda but not with Alexa, Invalid response. What gives? Is it because the Attributes are null?
12/26/2016 6:45 AM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
Yes, the return should be the proper JSON object as Alexa services do some automatic serialization of JSON data types to strings. I just updated the GitHub sample referenced as while the blog post showed returning the JSON object, the source code in my sample didn't (I forgot to commit the change).
12/26/2016 7:55 AM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
Thank you tim,
It works in lambda but not with Alexa, I am getting Invalid response. in Alexa.
12/27/2016 2:06 AM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
Hey Dipen

Are you able to get valid lambda response from Alexa testing ?
12/29/2016 3:38 PM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
Thanks for this, it's very timely.

But unless I'm missing something, the version of Slight.Alexa that's up in NuGet right now is the original Silvenga fork, and as you note above, it's not compatible with .Net core. Any chance you do a build of your fork and make it available in NuGet?
12/30/2016 9:58 AM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
Thank you Tim for your inspirational blog. I recently unpacked my Echo thinking I would explore its pros and cons and quickly realized I would have to look under the hood to really see whats going on. It proved to be reassuringly more complete than I first thought, meaning the Alexa Echo system consists of a rich set of layers for development, testing, security and deployment.

It took a few days to jump through all the hoops for researching/setting up AWS, Alexa Skills and VS 2015, but thanks to your guide here, I can now ask Alexa to add up numbers for me , and in hindsight, it doesn't seem unreasonably complex, it just appears overwhelming at times by the information overload.

cheers

1/2/2017 2:35 PM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
I had some issues due to the wrong references to slight.Alexa.core I think that a previous version was generating Json with the incorrect case... right now I got my c# lambda working returning an object and referencing the right slight.Alexa.Core great sample to start playing :)
1/3/2017 6:59 AM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
@stello - you are correct, the original owner of the NuGet package hasn't accepted my version yet. One thing you can do is look at my own personal fork though: www.nuget.org/packages/Alexa.NET/1.0.0-beta-1
1/5/2017 11:06 AM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
@tutu_helper and @Jay - I'm able to get a valid response from the test console and from my Echo device. I'm using the same code from my repository sample here: github.com/timheuer/alexa-csharp-lambda-sample
1/11/2017 4:41 PM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
hi Tim,

Super helpful. Glad you wrote this article. Unfortunately, when publishing my sample to AWS, I got the following error:

Executing publish command
... invoking 'dotnet publish', working folder '<removed>\bin\Release\netcoreapp1.0\publish'
... publish: Can not find runtime target for framework '.NETCoreApp,Version=v1.0' compatible with one of the target runtimes: 'win10-x64, win81-x64, win8-x64, win7-x64'. Possible causes:
... publish: 1. The project has not been restored or restore failed - run `dotnet restore`
... publish: 2. The project does not list one of 'win10-x64, win81-x64, win8-x64, win7-x64' in the 'runtimes' section.
... publish: 3. You may be trying to publish a library, which is not supported. Use `dotnet pack` to distribute libraries.

I tried manually doing "dotnet restore" and "dotnet pack", but that didn't help.

Appreciate your help! thanks.
1/12/2017 11:03 AM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
My new friend Kau helped me figure out the problem. In case others may experience the same problem. The fix was to add:

"runtimes": {
"win10-x64": {}
},

to the project.json file.

thanks.
1/16/2017 7:32 AM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
Hi Tim,

great Guide. I got everything up and running in no time. But i have the same problem that Alex Kau has:

How can u return "skillResponse" to string? (public string FunctionHandler(SkillRequest input, ILambdaContext context))

Thanks
1/19/2017 3:34 AM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
it works in lambda but not with Alexa, Invalid response. What gives? Is it because the Attributes are null?
Gravatar
1/20/2017 7:27 AM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
@Palladium

Download latest version of Tims example:
github.com/timheuer/alexa-csharp-lambda-sample
Download and add following package
www.nuget.org/packages/Alexa.NET/1.0.0-beta-1
Update package Slight.Alexa.Core to 1.0.10-Beta
www.nuget.org/.../1.0.10-beta

Try again. Should work now
1/25/2017 4:05 AM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
Great Guide. My skill works fine. I have only one problem: if i try to publish the AWS Lambda with ASW Toolkit in Visual Studio, the "Select Role" Combobox is always empty. As an result, the upload button keeps disabled.

It works fine with the command line tools "dotnet lambda package", that generate the zip file.

Have you any idea? Thanks!
1/26/2017 9:03 PM | # Nice post
Great blog. Very useful information, it clarified things a lot for us. Thanks for the wonderful post. - plunger pumps

www.dencilpumps.com/.../plunger-pumps.html
2/2/2017 5:15 PM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
Very useful. I was able to get the skill up and running, then make some modifications for fun.

I wanted to play with dynamoDB but am not having much luck finding information on using it in a C# Alexa Skill. Anyone have any ideas as to how to go about it?

Thanks again for the smaple C# skill,
Joe Lewis
2/4/2017 3:20 PM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
I tried, It works when upload manually. I tried to upload from Visual Studio and gets the "Select Role" Combobox empty and I cannot go further.
I tried my credential with the access key of users and root users but I cannot see the Roles. In AWS in function I able to see the Roles.

Do I missing something or it is a bug in the Visual Studio Kit ?
2/6/2017 6:20 AM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
Thanks for the insight. It's proved a useful resource for my development of an AI based conversation bot deployed via ASR. I have a question however regarding support for the built-in intent types. I have implemented both ILaunchRequest and IIntentRequest types of Slight.Alexa.Framework.Models.Requests.RequestTypes, but what I really need is access to the standard AMAZON types such as AMAZON.SearchAction, AMAZON.HelpIntent, AMAZON.StopIntent etc. Any idea if this is supported via the plugin and if so how do I filter on these AMAZON types? Any help would be most appreciated.
2/8/2017 3:49 PM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
For Hector V: ...

I ran into the same problem, where the "Roles" drop-down list was empty. Here is what you need to do:

(1) Go into the AWS console and select IAM from Services
(2) Add a User. Click on Add Permissions, then "Attach existing policies directly". I added a few permissions until step 3 worked as I had no clue which was needed, one of them I added was AWSLamdaFUllAccess.
(3) Once you have saved the user in IAM, go back into Visual Studio. When you try to Publish your skill, click on the "Add Another Account" icon next to the "Account profile to use" and create an account with the id and key of the IAM user you just added. Hopefully you will see entries in the Roles drop-down list (such as "lambda_exec_skillXxxxx" role).
3/10/2017 2:36 PM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
What is the best way that the .net lambda function can communicate over http with a rest-service over the internet? I use a .net-core HttpWebRequest but there is always a timeout error.
3/13/2017 4:33 PM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
now i have corrected my WebAPI-Service and the lambda-function.
but now, theres a DllNorFoundException (iphlpapi.dll) when i test my lambda-function.
3/22/2017 4:52 AM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
@Palladium, thank you! I wrestled with the 'works in test but not in Alexa' issue for a couple of days.
4/11/2017 11:17 AM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
Hi, great tutorial, but i'm struggling to get to the context object, specifically context.system.device. Any idea how this can be accomplished?

Thanks,
Ryan
4/24/2017 6:22 AM | # re: Write your Amazon Alexa Skill using C# on AWS Lambda services
Great article.

One issue I am having, when I send my skills response to ask a question, like "please say the name of an animal" it only waits 2 seconds, bleeps and then assumes an answer (it even fills the slot variable with the name of an animal.

Is there a way to tell it to wait for an answer and not just move on?

 
Please add 8 and 5 and type the answer here:

DISCLAIMER:

The opinions/content expressed on this blog are provided "ASIS" with no warranties and are my own personal opinions/content (unless otherwise noted) and do not represent my employer's view in any way.