.NET 6 and AWS: upgrade from .NET Core 3.1

Amazon recently announced that they had support for .NET 6 in their Lambda product, which was all that was holding me back from migrating forward from .NET Core 3.1.

The process was fairly simple - there are a few breaking changes in .NET 6 but nowhere near as many as there were moving from .NET core 2 to .NET core 3.

Development environment

I primarily use Debian Bullseye as my development environment (there must be dozens of us!). I do switch back to Windows 11 occasionally but Debian is far more productive if, like me, you're using Docker containers built using Linux to deploy things like web services. As I'm on Debian, I've ditched Visual Studio altogether and moved to Visual Studio Code for everything.

Install .NET 6

Microsoft supply a shell script for installing .NET as an alternative to using a package. I find the shell script much better, even though it's intended for CI/CD environments. installing .NET 6 is as simple as downloading the script, adding execute permission to it and running it:

drubie@chungus:~/Downloads$ ./dotnet-install.sh

By default it will install the latest version of .NET in a hidden directory in your account called .dotnet. You can simply add this directory to your path and you are good to go. The script has a version argument if you want earlier versions of the dotnet system.

Project file changes

In Visual Studio Code, change the "TargetFramework" to "net6.0" in all the .csproj files

Then you need to update the references in your projects. I had a few conflicts here and there that were fixed by removing all the code generators for Visual Studio that were a hangover from starting the project on Windows. I used the "Nuget Package Manager Gui" in Visual Studio Code to do that.

Fix the database connection issues if you have them

In my case, the MySQL database connection I use for Entity Framework has had a breaking change to the "UseMySql" method on the options builder, you need to add the server version to the connection string:

var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
var connString = System.Environment.GetEnvironmentVariable("DEFAULT_CONNECTION");
optionsBuilder.UseMySql(connString,ServerVersion.AutoDetect(connString));
var dbContext = new ApplicationDbContext(optionsBuilder.Options);

Depending on your system, you may have other changes you need to make before your system builds, but that was the primary issue for mine.

At that point, I checked everything into GitHub, went back to my Windows box to make sure everything built OK (it did) and proceeded to fixing up the AWS deployment files

Fix your aws-lambda-tools-default.json files

To target .NET 6, you need to change a couple of entries in the json file that controls how the lambda is deployed to AWS. AWS have actually added quite a few options for making better Lambda functions, including leveraging the code reduction efforts Microsoft have made to reduce boilerplate code. I was too lazy for that: my functions work as is so simply changing the environment was enough. The two settings are "framework" and "function-runtime". "framework" needs to match the framework you are targeting in your .csproj files i.e "net6.0". "function-runtime" should be set to "dotnet6".

{
    "Information" : [
        "This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.",
        "To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.",
        "dotnet lambda help",
        "All the command line options for the Lambda command can be specified in this file."
    ],
    "profile"     : "default",
    "region"      : "your-region",
    "configuration" : "Release",
    "framework"     : "net6.0",
    "function-runtime" : "dotnet6",
    "function-memory-size" : 3008,
    "function-timeout"     : 900,
    "function-handler"     : "AppBackupImporter::AppBackupImporter.Function::FunctionHandler",
    "function-name"        : "AppBackupImporter",
    "function-role"        : "your:role:stuff:here",
    "tracing-mode"         : "PassThrough",
    ...
    "function-description"  : "",
    "package-type"          : "Zip",
    "image-tag"             : ""
}

Fix your containers

You will need to use a .NET 6 ready container if you're using the off-the-shelf Microsoft ones. In my case, I switched over to a Debian container because that's what I'm using on my workstation. The Dockerfile now looks like:

FROM mcr.microsoft.com/dotnet/aspnet:6.0-bullseye-slim AS base

And that was it

The whole thing was pretty painless in the end. I did end up fiddling a bit with the openssl.cnf file in the base image but other than that, everything built and deployed as expected.

Visual Studio used to deploy my stuff using AWS toolkit

If you fell into the trap of using the AWS Toolkit to graphically deploy your lambdas and other systems, never fear as there is a better option in Debian: a good old Makefile. Make sure you have the AWS dotnet extensions installed. I found this much better than relying on Visual Studio to do everything, mostly because moving to something more complicated to deploy is easier if you already know what is going on under the covers.

This one for lambda functions. Note - you need a working "aws-lambda-tools-defaults.json" to make this work.

.PHONY: deploy

deploy:
	dotnet lambda deploy-function

This one for deploying a container to ECS. Note - you need a working "aws-ecs-tools-defaults.json" to make this work.

.PHONY: deploy

deploy:
	dotnet ecs deploy-service

On a Windows machine, fire up your WSL2 terminal to run those. It's kind of ironic that Microsoft making WSL2 nearly good was the final reason I needed to ditch their product for serious development. If you haven't investigated moving to a Linux environment for .NET development, I highly recommend looking into it, you can thank me later.

Popular posts from this blog

Tailscale ate my network (and I love it)

That magical word: Workstation

Time machine: Solaris 2.6 on QEMU