AWS Serverless applications with multiple .NET Core projects

When building a serverless application on AWS, AWS CloudFormation is incredibly important for deploying your AWS Lambda functions and the AWS resources that your application will interact with. With our AWS .NET Core Lambda tooling, when you create a serverless application an AWS CloudFormation template is added to your project. The template enables you to define your Lambda functions and other AWS resources. This means you can deploy multiple Lambda functions together.

When our .NET Core Lambda deployment executes, it builds the current .NET Core Lambda project, uploads the build artifacts to Amazon S3, updates the S3 locations in the AWS CloudFormation template, and then deploys the AWS CloudFormation template into an AWS CloudFormation stack with all of the Lambda functions.

Until recently, we had a limitation with our .NET Core Lambda deployment tooling. It only looked at the current directory for the .NET Core project and deployed that. This required you to code all the Lambda functions into the same .NET Core project, which could unnecessarily bloat the size of your Lambda deployment bundle.

As of version 3.1.0 of the Amazon.Lambda.Tools .NET Core Global tool, and the latest version of the AWS Toolkit for Visual Studio, you now have the ability to point the AWS CloudFormation template to different .NET Core projects for each Lambda function.

AWS Step Functions example

With AWS Step Functions you can define a state machine and invoke separate Lambda functions for each step along the state machine. In earlier versions of our tooling, you would need to define all of the Lambda functions in the same .NET Core project. But now we can define each step in a separate project, enabling you to develop and test each project independently.

Here is an example we recently showed at AWS re:Invent. In this Visual Studio solution, I have four separate projects for different stages in the state machine. One is even written in F#, showing how we can mix and match languages.

The AWS CloudFormation template is in a directory above the project directories. For each Lambda function defined in the serverless.template file, the S3Key property is set to the relative path of the directory that contains the .NET Core project for that Lambda function.

If the Lambda functions were defined as AWS::Serverless::Function resources, then the CodeUri property would have the relative location.

Because the serverless.template file isn’t under a .NET Core Lambda project, I don’t have a project to right-click and choose Publish to AWS Lambda in the toolkit. This is something we would like to improve in the future. If I wanted to keep the ability to deploy from Visual Studio, I would need to put the serverless.template file in a project and point to the other projects relative to that location.

When the deployment runs, it builds each of the projects and uploads the build artifacts to Amazon S3. Then deployment will update each Lambda function defined in the serverless.template to point to the S3 location for the project it is targeting. If the same project is referred to more than once, it’s built only once.

Referencing non .NET Core projects

The common scenario is to use the S3Key or CodeUri properties to point to a .NET Core project. But it’s also possible to refer to other types of code bundles for Lambda functions.

Here are the rules that the AWS .NET deployment tool uses:

If S3Key or CodeUri are blank, build the current directory.

If both S3Bucket and S3Key are set, or CodeUri is set to a full .S3 path, leave the properties as they are. This assumes the code artifacts are already uploaded to S3.

If S3Key or CodeUri are set to a .zip file, upload the .zip file.

If S3Key or CodeUri point to a file that isn’t a .zip file, then zip the file and upload it. This is useful when deploying a single file JavaScript function.

If S3Key or CodeUri are set to a local directory that doesn’t contain a .NET project file, zip the directory and upload it. This is useful when pointing to a directory that contains JavaScript or Python code.

If S3Key or CodeUri are set to a local directory that contains a .NET project, build the project and upload the build artifacts.