Deploy C# App on AWS Part (1/3)
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 itemitem_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()
andcreateRecord()
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 Requests
folder in the Models
folder and add CreateRecordResponse.cs
file to folder, also add CreateRecordRequest.cs
file to newly created Requests
folder.
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 SupabaseClient
which 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 theSupabaseService
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: