Deploy C# App on AWS Part (1/3)

Ali Alhaddad
7 min readJan 22, 2024

This is the beginning of a tutorial series that will go through how to deploy a dotnet 6 application on aws ecs.

What are we building?

  • A csharp dotnet application which would be a rest api that would mutate data from AWS. It would be specifically updating dynamodb, which is a nosql database.
  • We would integrate Supabase which is an open source firebase to manage our Postgresql database.
  • Push docker images to AWS ECR using PowerShell scripts.
  • Familiarize ourselves with other services of AWS such as IAM in order to create the software architecture mentioned in the previous three points.

First before we start you need to install certain tools. Make sure you install visual studio 2022 which would be used to create our csharp dotnet server.

Second install aws-cli, reference this start forward tutorial on how to install the aws-cli. Which would be responsible for creating and using aws services.

(NOTE: Create a aws free tier acccount first )

Third install dotnet cli to create dotnet 6 project. Reference how to install dotnet sdk, and tutorial on how to use the dotnet cli.

Fourth setup Supabase, reference this tutorial for setting up your supabase database instance.

Create a dotnet project using dotnet cli. Create a dotnet 6 project to be specific, use the --framework flag and name it whatever you want using the -n flag.

dotnet new webapi --framework net6.0 -n AwsTodoApp

Open Visual Studio, click on “Open Project or Solution,” and select the .csproj file. This action will automatically load the project into Visual Studio.

Install nuget packages you would need to use in order to access your aws services in your csharp project. Then search in browse and download supabase-csharp nuget package to use our Supabase services.

Before creating our data access object for accessing data from our PostgreSQL database, start by creating a table in Supabase. If you’ve already followed the tutorial above, feel free to skip this part. Name the table “todo-items” and assign it the following columns.

  • id is just a unique id.
  • item_name is the name of the item
  • item_type is the type of item.
  • importance is the importance of item which would be “Not Important”, “Somewhat Important”, “Important” and “Very Important”.

Now edit your project, and add endpoints to insert and get todo list items from newly created table.

Delete some placeholder files such as the WeatherForecast.cs file. Rename the WeatherForecastController to ListController.

Create a new folder named “Models” and establish a TodoItem class within it. This class will function in a manner akin to a DAO (Data Access Object) class in Entity Framework Core. Its purpose will be to facilitate the updating of the todo-items PostgreSQL table.

The content of our class would use two types of PostgreSQL decorators.

  • Table where you would pass your table name in a form of a string.
  • Column where you would pass your column in a form of a string.

Add another class that will be responsible for retrieving the todo item from the server. We are doing this because there are columns formatted specifically for the database that we don’t want our users to see.

In this case, they would be identical, but it’s good practice to separate classes that are responsible for inserting into the database from classes responsible for displaying to the user.

Add another folder called Services for our supabase service which would be an additional abstraction since each method would require the instantiation of the context in the context of a method. Add a SupabaseService.cs file to Services directory.

We’ll register our Supabase client and then create an abstraction that utilizes our Supabase service from our AWS SDK.

Register the client and assign it with the standard Supabase options mentioned in the tutorial above.

//Put this code right after the builder is instantiated using WebApplication.CreateBuilder or any other method
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");

var customConfig = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{environment}.json", optional: true, reloadOnChange: true)
.Build();
var supabaseConfig = new SupabaseConfiguration();
customConfig.GetSection("Supabase").Bind(supabaseConfig);
builder.Services.AddSingleton<SupabaseConfiguration>(supabaseConfig);

var options = new SupabaseOptions
{
AutoRefreshToken = true,
AutoConnectRealtime = true,
// SessionHandler = new SupabaseSessionHandler() <-- This must be implemented by the developer
};

builder.Services.AddSingleton(provider => new Supabase.Client(supabaseConfig.Url, supabaseConfig.AnonKey, options));
  • Supabase.Client is coming from supabase-csharp package.
  • The new SupabaseOptions(){} set options to the client upon registration. This is coming from the same supabase-csharp package.
    (supabase-csharp)

Create your SupabaseService that will be solely responsible for handling REST operations on the Supabase PostgreSQL table.

  • Create an interface with readRecords() and createRecord() methods, both designed to take generic types for reusability.
  • Next, create a class that implements this interface and utilizes a Supabase client from the Supabase library.

Let’s first the defined the custom classes that would be returned from our controller.

We first create a Responses folder in the Models folder and add ReadRecordsResponse.cs file to folder.

Second we would create a Requestsfolder in the Models folder and add CreateRecordResponse.cs file to folder, also add CreateRecordRequest.cs file to newly created Requestsfolder.

Now let’s finish the create record functionality first. First edit the request, add the item name, item type and importance.

NOTE: Might need to install Newtonsoft.Json to implement JsonProperty decorator.

Then edit the response, add just an id.

We will edit the CreateRecordAsync method, this will use the SupabaseClientwhich would use generic types with the From method to insert records. Generate a response for the newly created record.

Then define your ReadRecordsAsync method, that will return a list of todo items.

We integrate it with our controller that we called ListController.

  • Inject via the ISupabaseService interface that the SupabaseService class implements.
  • Remove irrelevant code and replace it with get and post endpoints.
  • In the get and post endpoints, return corresponding response types for reading and creating records.

Run it using dotnet run, or over visual studio UI.

Let’s now test our code in swagger.

First create a record, pass a itemName, itemType, and importance.

After navigating to your Supabase PostgreSQL table, you should observe the newly created items.

Now, let’s test our GET endpoint to retrieve all items from the PostgreSQL table. This is achieved through our GET request, as demonstrated in the gif, showcasing how records are fetched in the Supabase UI.

Congratulations, you’re halfway through your C# project! In the next step, we will finalize our project and define our Docker images.

2nd Part of Tutorial:

Last Part of Tutorial:

Here is our GitHub repository with the source code for reference:

--

--