In this tutorial, we'll be dipping our toes into the world of AWS Lambda and deploying a small C# lambda function to AWS using either .NET Core 7 or .NET Core 6.
Lambda functions allow you to run small or large chunks of code in the cloud. They're a great option for deploying backend logic for a web app, but to get started, we'll be deploying a simple function that takes a string as input and returns an uppercased version of that string.
In the next article, we'll take a look at how to use C# lambda functions to create a serverless API.
Dotnet Lambda Tools
We can use the .NET cli to create and deploy our Lambda function, but we'll need to install the Amazon.Lambda.Tools
package first.
dotnet tool install -g Amazon.Lambda.Tools
dotnet new install Amazon.Lambda.Templates
Now you can run the following command to view all the available templates:
dotnet new list
You should see a whole bunch of serverless
and lambda
templates now. To keep things simple, we'll be using the lambda.EmptyFunction
template
Function Setup
Lambda functions natively only support up to .NET 6. However, you can still use .NET 7 if you use docker, but you should make that decision now.
dotnet new lambda.EmptyFunction --name MyFunctionName
This will create a new directory called MyFunctionName
with a src
and a test
directory inside of it.
src
contains all the code that will run in AWS Lambda.test
contains all the unit tests for your function. We're going to ignore this for now.
Inside the src/MyFunctionName
directory, you'll find a Function.cs
file. This is the entry point for your function. Your code should look something like this:
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 MyFunctionName;
public class Function
{
public Casing FunctionHandler(string input, ILambdaContext context)
{
return new Casing(input.ToLower(), input.ToUpper());
}
}
public record Casing(string Lower, string Upper);
FunctionHandler
is the method that will be called when your function is invoked. It takes a string as input and returns an uppercased version of that string as it's output (in the Casing
class).
Console.WriteLine
statement to the FunctionHandler
method to log a message:public class Function
{
public Casing FunctionHandler(string input, ILambdaContext context)
{
Console.WriteLine($"My First Lambda Function, input: {input}");
return new Casing(input.ToLower(), input.ToUpper());
}
}
Let's deploy this function to AWS Lambda so we can test it out and see how it works.
Deploying to Lambda
Before we can deploy to AWS Lambda, we'll need to create an AWS account and configure our local machine with our AWS credentials. If you haven't done this already, Follow the AWS CLI instructions below to get started.
MyFunctionName/src/MyFunctionName
:Replace MyApp
with the name you want to use for your function in AWS.
dotnet lambda deploy-function MyFirstFunction
This will prompt you to select or create an IAM role for your Lambda function which will give your function access to other AWS services like CloudWatch Logs, DynamoDB, and S3. I recommend creating a new role for each lambda function you create as it will make it easier to manage permissions later on.
- Select the option that says *** Create new IAM Role *** when prompted.
- Give your role a name like MyFunctionName_Role so you can easily identify it later.
- Select the
AWSLambdaBasicExecutionRole
policy (option 6) so your function has basic access to CloudWatch Logs. This will allow your function to write logs and help you troubleshoot any issues that may arise.
Once you've selected the role and policy, the function will deploy. Every time you make an update to your code, just re-run the dotnet lambda deploy-function
command and your function will be updated.
Testing in the AWS Web Console
Make sure you're in your profile's default region, this is probably us-east-1.
Here you can manage your function's settings, view your function's logs and memory usage, and test your function.
Enter any name for the test and replace the Event JSON with a single string like "test string". This is going to be the input to the C# function that will hopefully return that text in all caps.
If you expande the Execution result section, you should see the output from your function.
You now have a serverless C# lambda function that you can execute through the web console. It's very basic but it's the start of building much more complex serverless applications. This is just the beinning. Feel free to tweak the code and redeploy to see how it works.
Cloudwatch Logs
You might be wondering where the Console.WriteLine
log message went. It's not in the execution result section of the test event. That's because the stdout from your lambda functions gets sent to another service in AWS called cloudwatch. Sometime to get used to when it comes to severless applications, almost everything is an additional service.
To view the logs:
- Click the Monitoring tab.
- Click the View logs in CloudWatch button. This sends you to the log group in cloud watch for the current lambda function.
- Select the top log stream. Each time you deploy a new version of your function, a new log stream is created with the newest one always on top.
Once you've selected the log stream, you can view all the logs for that function. Both internal lambda logs and your own logs created with Console.WriteLine
. Expand any logs in between a START RequestId
and END RequestId
to see the logs for a single execution of your function.
Summary
Lambda functions allow you to run small or large chunks of code in the cloud. They're a great option for deploying backend logic for a web app, and in the next article, we'll take a look at how to use C# lambda functions to create a serverless API.