How to create AWS Lambda Function with Dotnet CLI Templates

Find project in https://github.com/csharp-projects-kenanhancer/greeting-aws-lambda-function

Installing dotnet tools

Find more details about Amazon.Lambda.Tools in Amazon.Lambda.Tools

$ dotnet tool install -g Amazon.Lambda.Tools
$ dotnet tool update -g Amazon.Lambda.Tools

Find more details in The AWS .NET Mock Lambda Test Tool

$ dotnet tool install -g Amazon.Lambda.TestTool-6.0
$ dotnet tool update -g Amazon.Lambda.TestTool-6.0
$ dotnet tool list -g 
Package Id                      Version      Commands                   
------------------------------------------------------------------------
amazon.lambda.testtool-6.0      0.13.1       dotnet-lambda-test-tool-6.0
amazon.lambda.tools             5.7.2        dotnet-lambda  

Lambda offers additional templates via the Amazon.Lambda.Templates NuGet package. To install this package, run the following command:

The ::* on the end of the command indicates the latest version of the NuGet package.

Creating dotnet lambda function project

$ dotnet new install "Amazon.Lambda.Templates::*"
$ dotnet new list --author AWS
These templates matched your input: author='AWS'

Template Name       Short Name                                    Language  Tags                            
------------------  --------------------------------------------  --------  --------------------------------
Empty Top-level...  lambda.EmptyTopLevelFunction                  [C#]      AWS/Lambda/Serverless           
Lambda Annotati...  serverless.Annotations                        [C#]      AWS/Lambda/Serverless           
Lambda ASP.NET ...  serverless.AspNetCoreMinimalAPI               [C#]      AWS/Lambda/Serverless           
Lambda ASP.NET ...  serverless.AspNetCoreWebAPI                   [C#],F#   AWS/Lambda/Serverless           
Lambda ASP.NET ...  serverless.image.AspNetCoreWebAPI             [C#],F#   AWS/Lambda/Serverless           
Lambda ASP.NET ...  serverless.AspNetCoreWebApp                   [C#]      AWS/Lambda/Serverless           
Lambda Custom R...  lambda.CustomRuntimeFunction                  [C#],F#   AWS/Lambda/Function             
Lambda Detect I...  lambda.DetectImageLabels                      [C#],F#   AWS/Lambda/Function             
Lambda Empty Fu...  lambda.EmptyFunction                          [C#],F#   AWS/Lambda/Function             
Lambda Empty Fu...  lambda.image.EmptyFunction                    [C#],F#   AWS/Lambda/Function             
Lambda Empty Se...  serverless.EmptyServerless                    [C#],F#   AWS/Lambda/Serverless           
Lambda Empty Se...  serverless.image.EmptyServerless              [C#],F#   AWS/Lambda/Serverless           
Lambda Function...  lambda.NativeAOT                              [C#],F#   AWS/Lambda/Function             
Lambda Function...  lambda.Powertools                             [C#]      AWS/Lambda/Function/Powertools  
Lambda Giraffe ...  serverless.Giraffe                            F#        AWS/Lambda/Serverless           
Lambda Serverle...  serverless.Powertools                         [C#]      AWS/Lambda/Serverless/Powertools
Lambda Simple A...  lambda.SimpleApplicationLoadBalancerFunction  [C#]      AWS/Lambda/Function             
Lambda Simple D...  lambda.DynamoDB                               [C#],F#   AWS/Lambda/Function             
Lambda Simple K...  lambda.KinesisFirehose                        [C#]      AWS/Lambda/Function             
Lambda Simple K...  lambda.Kinesis                                [C#],F#   AWS/Lambda/Function             
Lambda Simple S...  lambda.S3                                     [C#],F#   AWS/Lambda/Function             
Lambda Simple S...  lambda.SNS                                    [C#]      AWS/Lambda/Function             
Lambda Simple S...  lambda.SQS                                    [C#]      AWS/Lambda/Function             
Lex Book Trip S...  lambda.LexBookTripSample                      [C#]      AWS/Lambda/Function             
Order Flowers C...  lambda.OrderFlowersChatbot                    [C#]      AWS/Lambda/Function             
Serverless Dete...  serverless.DetectImageLabels                  [C#],F#   AWS/Lambda/Serverless           
Serverless proj...  serverless.NativeAOT                          [C#],F#   AWS/Lambda/Serverless           
Serverless Simp...  serverless.S3                                 [C#],F#   AWS/Lambda/Serverless           
Serverless WebS...  serverless.WebSocketAPI                       [C#]      AWS/Lambda/Serverless           
Step Functions ...  serverless.StepFunctionsHelloWorld            [C#],F#   AWS/Lambda/Serverless           

$ dotnet new lambda.EmptyFunction --name lambda-function1
$ code lambda-function1
using Amazon.Lambda.Core;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace lambda_function1;

public class Function
{
    
    /// <summary>
    /// A simple function that takes a string and does a ToUpper
    /// </summary>
    /// <param name="input"></param>
    /// <param name="context"></param>
    /// <returns></returns>
    public string FunctionHandler(string input, ILambdaContext context)
    {
        return input.ToUpper();
    }
}
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
    <AWSProjectType>Lambda</AWSProjectType>
    <!-- This property makes the build directory similar to a publish directory and helps the AWS .NET Lambda Mock Test Tool find project dependencies. -->
    <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
    <!-- Generate ready to run images during publishing to improve cold start time. -->
    <PublishReadyToRun>true</PublishReadyToRun>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Amazon.Lambda.Core" Version="2.1.0" />
    <PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="2.3.1" />
  </ItemGroup>
</Project>
.
├── .vscode
│   ├── launch.json
│   └── tasks.json
├── src
│   └── lambda-function1
│       ├── Function.cs
│       ├── Readme.md
│       ├── aws-lambda-tools-defaults.json
│       ├── bin
│       │   └── Debug
│       │       └── net6.0
│       │           ├── Amazon.Lambda.Core.dll
│       │           ├── Amazon.Lambda.Serialization.SystemTextJson.dll
│       │           ├── lambda-function1.deps.json
│       │           ├── lambda-function1.dll
│       │           ├── lambda-function1.pdb
│       │           └── lambda-function1.runtimeconfig.json
│       ├── lambda-function1.csproj
│       └── obj
│           ├── Debug
│           │   └── net6.0
│           │       ├── .NETCoreApp,Version=v6.0.AssemblyAttributes.cs
│           │       ├── lambda-function1.AssemblyInfo.cs
│           │       ├── lambda-function1.AssemblyInfoInputs.cache
│           │       ├── lambda-function1.GeneratedMSBuildEditorConfig.editorconfig
│           │       ├── lambda-function1.GlobalUsings.g.cs
│           │       ├── lambda-function1.assets.cache
│           │       ├── lambda-function1.csproj.AssemblyReference.cache
│           │       ├── lambda-function1.csproj.CopyComplete
│           │       ├── lambda-function1.csproj.CoreCompileInputs.cache
│           │       ├── lambda-function1.csproj.FileListAbsolute.txt
│           │       ├── lambda-function1.dll
│           │       ├── lambda-function1.genruntimeconfig.cache
│           │       ├── lambda-function1.pdb
│           │       ├── ref
│           │       └── refint
│           ├── lambda-function1.csproj.nuget.dgspec.json
│           ├── lambda-function1.csproj.nuget.g.props
│           ├── lambda-function1.csproj.nuget.g.targets
│           ├── project.assets.json
│           └── project.nuget.cache
└── test
    └── lambda-function1.Tests
        ├── FunctionTest.cs
        ├── bin
        │   └── Debug
        │       └── net6.0
        ├── lambda-function1.Tests.csproj
        └── obj
            ├── Debug
            │   └── net6.0
            │       ├── .NETCoreApp,Version=v6.0.AssemblyAttributes.cs
            │       ├── lambda-function1.Tests.AssemblyInfo.cs
            │       ├── lambda-function1.Tests.AssemblyInfoInputs.cache
            │       ├── lambda-function1.Tests.GeneratedMSBuildEditorConfig.editorconfig
            │       ├── lambda-function1.Tests.GlobalUsings.g.cs
            │       ├── lambda-function1.Tests.Program.cs
            │       ├── lambda-function1.Tests.assets.cache
            │       ├── lambda-function1.Tests.csproj.AssemblyReference.cache
            │       ├── ref
            │       └── refint
            ├── lambda-function1.Tests.csproj.nuget.dgspec.json
            ├── lambda-function1.Tests.csproj.nuget.g.props
            ├── lambda-function1.Tests.csproj.nuget.g.targets
            ├── project.assets.json
            └── project.nuget.cache

Debugging

click CMD+SHIFT+P and type .NET: Generate Assets for Build and Debug to add debug config in project(.vscode folder will be generated automatically)

Debugger didn't run directly so I updated configuration files(launch.json and tasks.json) as below;

Use the following path in program field for macOS in launch.json

<home-directory>/.dotnet/tools/.store/amazon.lambda.testtool-6.0/<nuget-version>/amazon.lambda.testtool-6.0/<nuget-version>/tools/net6.0/any/Amazon.Lambda.TestTool.BlazorTester.dll

Or try the following;

${env:HOME}/.dotnet/tools/dotnet-lambda-test-tool-6.0
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": ".NET Core Launch (console)",
      "type": "coreclr",
      "request": "launch",
      // "program": "${env:HOME}/.dotnet/tools/dotnet-lambda-test-tool-6.0",
      "program": "${env:HOME}/.dotnet/tools/.store/amazon.lambda.testtool-6.0/0.13.1/amazon.lambda.testtool-6.0/0.13.1/tools/net6.0/any/Amazon.Lambda.TestTool.BlazorTester.dll",
      "args": [],
      "cwd": "${workspaceFolder}",
      "console": "internalConsole",
      "preLaunchTask": "build",
      "stopAtEntry": false,
      "internalConsoleOptions": "openOnSessionStart"
    },
    {
      "name": ".NET Core Attach",
      "type": "coreclr",
      "request": "attach"
    }
  ]
}

Update lambda-function1 in terms of your project name in the following tasks.json

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "build",
      "command": "dotnet",
      "type": "process",
      "args": [
        "build",
        "${workspaceFolder}/src/lambda-function1/lambda-function1.csproj",
        "/property:GenerateFullPaths=true",
        "/consoleloggerparameters:NoSummary"
      ],
      "problemMatcher": "$msCompile"
    },
    {
      "label": "publish",
      "command": "dotnet",
      "type": "process",
      "args": [
        "publish",
        "${workspaceFolder}/src/lambda-function1/lambda-function1.csproj",
        "/property:GenerateFullPaths=true",
        "/consoleloggerparameters:NoSummary"
      ],
      "problemMatcher": "$msCompile"
    },
    {
      "label": "watch",
      "command": "dotnet",
      "type": "process",
      "args": [
        "watch",
        "run",
        "--project",
        "${workspaceFolder}/src/lambda-function1/lambda-function1.csproj"
      ],
      "problemMatcher": "$msCompile"
    }
  ]
}

Click F5 to start debugger and browser will be opened automatically. Lambda function's input type is string in line 17 in the following screenshot so we have to send a string value in double quotes from web UI below.

If debugging doesn't work, you can close vscode completely and open again, than it works 🙂

Result