AWS Lambda functions allow developers to run code without creating or managing highly-available infrastructure. As of the creation of this post, there are two ways to deploy your source code as a Lambda Function. Creating a .ZIP archive or packaging the application as docker image.

Lambda functions can be used as triggers for other aws resources (e.g a file is uploaded to an S3 bucket). They can also consumed by web or mobile applications using something like a RESTful API.

In this post, I’ll walk through setting up a .NET 5 Web API as a Lambda function and exposing the API using Amazon API Gateway.

As always, if you know of a better method for the problems below, find a mistake, have the answer to a question below let me hear about it, i’ll update the post Contact Form

Requirements

  • AWS Account
  • AWS CLI 2
  • Visual Studio 2019
  • .NET 5 Framework

Project Setup

Before you start, you’ll want to setup an S3 bucket in the region that makes sense to you (I’m using us-east-1). You can accomplish this by either using the AWS Console or the AWS CLI.

aws s3api create-bucket --bucket firstlambda.test001 --region us-east-1

After creating the S3 bucket, you’ll want to have the Lambda ASP.NET Core Web API (.NET 5 Container Image) template installed locally. You can check if you have this installed by running the commands below..

dotnet new -l
Lambda ASP.NET Core Web API                           serverless.AspNetCoreWebAPI                   [C#],F#     AWS/Lambda/Serverless 
Lambda ASP.NET Core Web API (.NET 5 Container Image)  serverless.image.AspNetCoreWebAPI             [C#],F#     AWS/Lambda/Serverless 
Lambda ASP.NET Core Web Application with Razor Pages  serverless.AspNetCoreWebApp                   [C#]        AWS/Lambda/Serverless 
Serverless Detect Image Labels                        serverless.DetectImageLabels                  [C#],F#     AWS/Lambda/Serverless 
Lambda DynamoDB Blog API                              serverless.DynamoDBBlogAPI                    [C#]        AWS/Lambda/Serverless 
Lambda Empty Serverless                               serverless.EmptyServerless                    [C#],F#     AWS/Lambda/Serverless 
Lambda Empty Serverless (.NET 5 Container Image)      serverless.image.EmptyServerless              [C#],F#     AWS/Lambda/Serverless 
Lambda Giraffe Web App                                serverless.Giraffe                            F#          AWS/Lambda/Serverless 
Serverless Simple S3 Function                         serverless.S3                                 [C#],F#     AWS/Lambda/Serverless 
Step Functions Hello World                            serverless.StepFunctionsHelloWorld            [C#],F#     AWS/Lambda/Serverless 
.....

You’ll then want to create the project specifying the name of project below.

dotnet new install -g Amazon.Lambda.Templates

After installing the templates, create the project

dotnet new serverless.image.AspNetCoreWebAPI --name FirstLambda

Project Structure

The structure below is what the template should have generated. If you have been working with .NET Web API Projects the Program.cs file should sound familiar. In this template, there are two files: LambdaEntryPoint.cs, LocalEntryPoint.cs used similarly to the Program.cs file.

  • LambdaEntryPoint.cs - The “lambda program.cs” file for the application running as a lambda function.
  • LocalEntryPoint.cs - The “local program.cs” file that comes with the standard template. (Used locally)
  • aws-lambda-tools-defaults.json - set the options in this file for Lambda tooling. For example, the timeout period for the lambda function.
  • serverless.template
FirstLambda
├── src
│   └── FirstLambda
│       ├── Controllers
│       │   └── ValuesController.cs
│       ├── Dockerfile
│       ├── FirstLambda.csproj
│       ├── LambdaEntryPoint.cs
│       ├── LocalEntryPoint.cs
│       ├── Readme.md
│       ├── Startup.cs
│       ├── appsettings.Development.json
│       ├── appsettings.json
│       ├── aws-lambda-tools-defaults.json
│       └── serverless.template
└── test
    └── FirstLambda.Tests
        ├── FirstLambda.Tests.csproj
        ├── SampleRequests
        │   └── ValuesController-Get.json
        ├── ValuesControllerTests.cs
        └── appsettings.json

6 directories, 15 files

Containairze The Application

Looking at the Dockerfile the template contains, you’ll find The docker image is built from the build output generated after the application is built on your machine. Once built, the docker image copies the binaries from bin/Release/net5.0/linux-x64/publish.

FROM public.ecr.aws/lambda/dotnet:5.0

WORKDIR /var/task

COPY "bin/Release/net5.0/linux-x64/publish"  .

Optionally, you can modify the Dockerfile to build the .NET Lambda project inside the image.

FROM public.ecr.aws/lambda/dotnet:5.0 AS base 

FROM mcr.microsoft.com/dotnet/sdk:5.0-focal AS build 
WORKDIR /src
COPY FirstLambda.csproj FirstLambda/
RUN dotnet restore FirstLambda/FirstLambda.csproj --source https://api.nuget.org/v3/index.json

WORKDIR /src/FirstLambda
COPY . .
RUN dotnet build FirstLambda.csproj -c Release -o /app

FROM build AS publish
RUN dotnet publish FirstLambda.csproj -c Release --runtime linux-x64 --self-contained false -o /app -p:PublishReadyToRun=true 

FROM base AS final
WORKDIR /var/task
COPY --from=publish /app .

👋 PLZ SUBSCRIBE

No Spam. Unsubscribe easily at any time.

🎊 🎉 Thanks For Your Subscription!

Publish Application

Now, we’ll want to publish the application and examine the outputs… After running the command below, You’ll be prompted for the name of the s3 bucket you created at the begining of the post a name for a cloudformation resource.

dotnet lambda deploy-serverless --region us-east-1
.....
Stack finished updating with status: CREATE_COMPLETE
   
Output Name                    Value                                             
------------------------------ --------------------------------------------------
ApiURL                         https://removed.execute-api.us-east-1.amazonaws.com/Prod/
Stack finished updating with status: CREATE_COMPLETE

‘Issues I Encountered’ 🤬

  • If you don’t specify the correct region, your aws cli commands tend to time out.
  • You must build your Docker image from public.ecr.aws/lambda/dotnet:5.0