Skip to main content

With the announcement of the new C# runtime in AWS Lambda, enterprises are now able to start taking their .NET investment into the world of serverless applications. In this blog post, I want to help you get up and running with .NET Core using the new AWS Serverless Application Model (SAM) transform for AWS CloudFormation. We’re going to build a simple “Hello World” API endpoint by deploying a resource in Amazon API Gateway and a C# function in AWS Lambda.

The Code:

Like a normal .NET Core project, let’s create a new directory:

mkdir csharplambda
cd csharplambda
dotnet new

Now we need to make some changes to our project.json file. Make sure it looks something like this:
As a quick aside, if you examine the project.json, you’ll notice the Amazon.Lambda.Serialization.Json dependency; this allows us to serialize POCO (Plain Old CLR/C# Object)s into JSON, which we’ll need later. I also add a dependency on Newtonsoft.Json so I can customize the output of that JSON payload later. Finally, notice the .NET core version: netcoreapp1.0; this is not the latest version of the .NET Core runtime; however, this is the latest version supported by AWS Lambda, so that’s what we’ll target so we don’t have any unexpected “works on my machine” surprises.
Now we need to run dotnet restore to fetch all of those dependencies. After that, we’ll move on to the program.cs file. Since AWS Lambda doesn’t act like a normal command line application, we’re not going to have the same kind of boilerplate Main method. Instead, we need to create a method for the Lambda handler to execute. Replace the contents of Program.cs with the following:
If we compile this code, we’ll get an assembly called csharplambda::CSharpFunction.HelloWorld::Handler, this is because our root directory where the project.json is stored is called csharplambda; the namespace of our Program.cs is CSharpFunction; the class is HelloWorld and the method is called Handler. You’ll notice we have two POCOs, Headers and Response, and we create instances of those in the Handler method where we write out the payload for AWS Lambda to tell Amazon API Gateway what to send to the client. The LambdaSerializer data annotation tells the method to serialize the POCOs into JSON.

Publishing and Packaging:

At this point you should have only 3 files:

  • Program.cs
  • project.json
  • project.lock.json (which was created when you ran dotnet restore)

Now we’re going to package this Lambda function. To do this, run dotnet publish and your code compiles. The path to the output will likely be something like ./bin/Debug/netcoreapp1.0/publish. This is the source directory that we’ll refer to in our CloudFormation template.
Create a new file next to project.json called csharplambda.yaml – you can name this whatever you want, but end it in “.yaml”. Insert these contents:
In this CloudFormation template, we reference Transform: AWS::Serverless-2016-10-31. This allows us to use the new Serverless Application Model language that AWS recently launched. We specify a function called CSharpHelloWorld with the Handler of csharplambda::CSharpFunction.HelloWorld::Handler and the Runtime of dotnetcore1.0 (this allows us to use C#). We also set the CodeUri to ./bin/Debug/netcoreapp1.0/publish; this local path will allow the AWS CLI to automatically zip up the contents and upload to an S3 bucket of our choosing. Finally, under Events, we declare the API Gateway endpoint. The resource is called HelloResource and the path is /hello and we’re only supporting an HTTP GET.
Now, if you already have the AWS CLI installed, you can create an S3 bucket for your code like this:

aws s3 mb s3://my-unique-bucket-123

We’re ready to package everything we have. Run the following command:

aws cloudformation package --template-file csharplambda.yaml --output-template-file serverless-output.yaml --s3-bucket my-unique-bucket-123

This command zips up that code, sends it to S3 and then produces a file called serverless-output.yaml that references the code. Now we’re ready to deploy!
To ship our stack, we can run the following command:

aws cloudformation deploy --template-file serverless-output.yaml --stack-name csharplambda --capabilities CAPABILITY_IAM

This creates a transform change-set and then a CloudFormation stack. If you log in to the AWS Console, you can now go to API Gateway, find the csharplambda API, go to Stages and find the Prod/Stage URLs to test. If you drill down to the /hello resource, you’ll find the Invoke URL. If you click on it, you’ll be pleasantly presented with the seminal words: “Hello World.”


You’ll find the Invoke URL in API Gateway Stages.

Other Resources

Now is a good time to mention, I just shipped a Live Lab: Building a Serverless Application End-to-End. In the lab, you’ll be able to watch me apply the concepts that were covered in this post. In addition, you’ll get a temporary AWS account to go and deploy your own serverless application. In the lab, you’ll use JavaScript and you’ll get a little more advanced than a Hello World, even grabbing state from DynamoDB. Try it out, I’d love to get your feedback for future labs!


Image of Jeff
4 years ago

Cool stuff, I just wish aws lambda would also hurry up and get support for go (golang) so I don’t have to keep running my binaries through a nodejs wrapper.

Image of JohnnyJelinek
4 years ago

I know, right? I bet they’ll release Go support in 2017.

Image of Krishnan
4 years ago

It will be nice if you can post something like this for JAVA from Alexa perspective. All the sample I see is on NodeJS. Not that I am against it, I’d love to see an end to end picture for Alexa in Java

Image of JohnnyJelinek
4 years ago

Do you mean you would like to see an app for Amazon Alexa using AWS Lambda and Java? I could definitely see an upcoming blog post on that topic, or even a live lab! Thanks for the suggestion!

Image of ben
3 years ago

what sort of .Net project do you create to do this?
a .NET Core Class Library?

Image of Johnny Jelinek
Johnny Jelinek
3 years ago

Start with a normal .NET core command line application.


Leave a Reply

Your email address will not be published. Required fields are marked *