So you basically logged in already but have no projects? you can either create the same one I am or your own example, pretty much anything goes. Access Supabase Dashboard.
New Project
Name
for your ProjectPassword
or generate one, be sure to store password in a safe place if generated.Region
closest to youPricing Plan
Table Editor
: This is basically where we go to look at the tables we have in our databaseCreate a new Table
: Basically we need a table to store our Artists.
Add artists
into name: You’re able to set Row Level Security
and support for real-time supscriptions
Row Level Security
for now , makes things easier for our APIcolumns
you want to haveYou will already have id
set as your Primary key , with created_at
for the date by default. I added another column called songs_released
as an int4
, basically, it can store numbers up to around 2.1 billion and we removed email
.
Now that our table is completely set up , let’s insert
some dummy data.
So when we insert some dummy data in here , you got a pretty convinient way of adding it via the UI, there’s definetly ways you can do this in bulk, but for this tutorial, we’ll use the UI.
Once filling in the information, hit save
. Now we got some data.
The Supabase C# Client is a community-driven library that allows C# developers to interact with Supabase services, including Postgres databases, authentication, real-time subscriptions and storage.
For more details, you can refer to the official documentation and the GitHub repository.
So you can definetly look at the tutorial project for some guidance on specific things. I have done a seperation of concerns regarding the services and dependencies in the project.
There’s two ways to make this happen:
Funny story , I was following a tutorial right and then I wanted to use the supacbase-c-sharp
package only to find out, it has been depricated, in other words we freestyled the rest of this
dotnet add package Supabase --version 1.1.1
Dependencies
Manage Nuget Packages
Browse
TabSupabase
& Install
After installing the Supabase package, we need to configure it in our application. Let’s create a proper setup to inject the Supabase client into our services so we can use it throughout our API.
First, we’ll create a extension class that will handle the Supabase client setup:
namespace Supabase.TutorialOne.Extensions
{
public static class SupabaseConfig
{
public static void AddSupabaseService(this IServiceCollection services, string url, string key)
{
services.AddScoped<Client>(provider =>
{
var options = new SupabaseOptions
{
AutoRefreshToken = true,
AutoConnectRealtime = true
};
var supabaseClient = new Client(url, key, options);
supabaseClient.InitializeAsync().Wait();
return supabaseClient;
});
}
}
}
This extension method:
Wait()
call makes sure initialization completes before returning)Add your Supabase URL and key to the application settings:
{
"Supabase": {
"Url": "YOUR_SUPABASE_URL",
"Key": "YOUR_SUPABASE_KEY"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
⚠️ Important: In a production environment, never commit these secrets to your repository. Use a secure secrets management approach like user secrets or environment variables.
To keep our Program.cs clean and maintainable, we’ll create a dependencies configuration extension:
namespace Supabase.TutorialOne.Extensions
{
public static class DependenciesConfig
{
public static void AddDependencies(this WebApplicationBuilder builder)
{
builder.Services.AddOpenApiService();
var supabaseUrl = builder.Configuration["Supabase:Url"];
var supabaseKey = builder.Configuration["Supabase:Key"];
builder.Services.AddSupabaseService(supabaseUrl, supabaseKey);
}
}
}
This extension:
AddSupabaseService
method to configure the clientOur Program.cs file remains clean and straightforward:
using Supabase.TutorialOne.Extensions;
var builder = WebApplication.CreateBuilder(args);
builder.AddDependencies();
var app = builder.Build();
app.UseOpenApiService();
app.UseHttpsRedirection();
app.Run();
We’ve kept our Program.cs clean and focused by:
builder.AddDependencies()
call instead of cluttering it with service registrationsThis approach makes our program more maintainable and easier to understand, especially for beginners. It also allows us to easily add more services in the future without making Program.cs more complex.
To make your application work with Supabase, you’ll need your project URL and API key:
To interact with our Supabase database, we need to create model classes that represent our database tables. These models map database columns to C# properties, allowing us to work with database records as objects in our code.
Let’s create a model for our artists
table:
using Supabase.Postgrest.Attributes;
using Supabase.Postgrest.Models;
namespace Supabase.TutorialOne.Models
{
[Table("artists")]
public class ArtistManagement : BaseModel
{
[PrimaryKey("id",false)] // this is auto-generated
public long Id { get; set; }
[Column("full_name")]
public string FullName { get; set; } = string.Empty;
[Column("stage_name")]
public string? StageName { get; set; }
[Column("genre")]
public string? Genre { get; set; }
[Column("bio")]
public string? Bio { get; set; }
[Column("songs_released")]
public int? SongsReleased { get; set; }
[Column("is_active")]
public bool? IsActive { get; set; }
[Column("created_at")]
public DateTime? CreatedAt { get; set; }
}
}
Our ArtistManagement
model:
Inherits from BaseModel
(provided by Supabase) which gives it functionality for working with Postgrest
Uses Supabase attributes to map to our database table:
[Table("artists")]
- Maps the class to the “artists” table in Supabase[PrimaryKey("id", false)]
- Maps the Id property to the primary key column, with false
indicating it’s auto-generated[Column("column_name")]
- Maps each property to its corresponding database columnIncludes nullable types (string?
, int?
, etc.) for optional fields, making them more flexible
These are specifically designed to work with Supabase’s API and provide the correct mapping between your C# code and the Supabase database.
Now that we’ve created our model, we’re ready to build API endpoints that will use this model to interact with our Supabase database.
After creating our model, we need to establish endpoint structures that will allow our API to interact with Supabase. Let’s create a file to handle these endpoints:
namespace Supabase.TutorialOne.Endpoints
{
public static class ArtistEndpoint
{
public static void AddArtistEndpoints(this WebApplication app)
{
// Add the endpoints for the artist management
}
// Classes to map the request and response for Artists
public class CreateArtistRequest
{
public string FullName { get; set; } = string.Empty;
public string? StageName { get; set; }
public string? Genre { get; set; }
public string? Bio { get; set; }
public int? SongsReleased { get; set; }
public bool? IsActive { get; set; }
}
public class ArtistRequestResponse
{
public long Id { get; set; }
public string FullName { get; set; } = string.Empty;
public string? StageName { get; set; }
public string? Genre { get; set; }
public string? Bio { get; set; }
public int? SongsReleased { get; set; }
public bool? IsActive { get; set; }
public DateTime? CreatedAt { get; set; }
}
}
}
Extension Method Pattern: We’re using an extension method (AddArtistEndpoints
) that will allow us to easily add these endpoints to our application in Program.cs.
Data Transfer Objects (DTOs):
CreateArtistRequest
: Defines the shape of data coming from clients when creating an artistArtistRequestResponse
: Defines the shape of data we send back to clientsSeparation of Concerns: By keeping our request/response models separate from our database model, we:
This setup prepares us for implementing actual API endpoints that will interact with our Supabase database using our model. In the next section, we’ll add the actual functionality to create, retrieve, and delete artists.
Let’s take a quick detour to look at PostgREST
PostgREST is a tool that instantly turns your PostgreSQL database into a RESTful API. If you’re using Supabase like we are, we already have access to a PostgREST server right out the box. Which will expose a RESTful API with CRUD endpoints for our database. The endpoints we going to build are already available with PostgREST and we wont need to create it from scratch. Basically the route we taking in this tutorial is just to showcase, “how” if you wanted to add extra business logic to your CRUD operations.
Now that we have set up our models and endpoint structure, let’s implement the actual API endpoints to interact with our Supabase database. We’ll create three basic CRUD operations: POST (create), GET (read), and DELETE.
POST
EndpointThe POST endpoint allows clients to create a new artist in our database:
app.MapPost("/artists", async (CreateArtistRequest request, Supabase.Client client) =>
{
var artist = new ArtistManagement
{
FullName = request.FullName,
StageName = request.StageName,
Genre = request.Genre,
Bio = request.Bio,
SongsReleased = request.SongsReleased,
IsActive = request.IsActive,
CreatedAt = DateTime.UtcNow
};
var response = await client.From<ArtistManagement>().Insert(artist);
var newArtist = response.Models.First();
return Results.Ok(newArtist.Id);
});
This endpoint:
CreateArtistRequest
object from the request bodyArtistManagement
object from the request dataGET
EndpointThe GET endpoint retrieves a specific artist by ID:
app.MapGet("/artists/{id}", async (long id, Supabase.Client client) =>
{
// this is our body, supabase supports LINQ queries
var response = await client
.From<ArtistManagement>()
.Where(n => n.Id == id)
.Get();
var artists = response.Models.FirstOrDefault();
if (artists is null)
{
return Results.NotFound();
}
var artistResponse = new ArtistRequestResponse
{
Id = artists.Id,
FullName = artists.FullName,
StageName = artists.StageName,
Genre = artists.Genre,
Bio = artists.Bio,
SongsReleased = artists.SongsReleased,
IsActive = artists.IsActive,
CreatedAt = artists.CreatedAt
};
return Results.Ok(artistResponse);
});
This endpoint:
DELETE
EndpointThe DELETE endpoint removes an artist from the database:
app.MapDelete("/artists/{id}", async (long id, Supabase.Client client) =>
{
await client
.From<ArtistManagement>()
.Where(n => n.Id == id)
.Delete();
return Results.Ok();
});
This endpoint:
To make these endpoints available in our application, we need to call our extension method in Program.cs:
app.AddArtistEndpoints();
This single line registers all our artist endpoints with the application. The complete Program.cs file now looks like:
using Supabase.TutorialOne.Endpoints;
using Supabase.TutorialOne.Extensions;
var builder = WebApplication.CreateBuilder(args);
builder.AddDependencies();
var app = builder.Build();
app.UseOpenApiService();
app.UseHttpsRedirection();
app.AddArtistEndpoints();
app.Run();
We’ll test our API to ensure it’s working correctly with our Supabase database.
Surprised we using Postman? me too. Im still getting into it myself.
But just to assure you that things are happening right? we can still view if information is coming through from Supabase
Run
your ProjectChange
your url from
https://localhost:7060
to , be sure to add actually Id like 1
, not {id}
https://localhost:7060/artists/{id}
You should then see something like this:
woohoo! we got an artist coming from our Supabase database
Below is a step-by-step guide for testing the Supabase artist endpoints using Postman. Since our API is running at https://localhost:7060
https://localhost:7060/artists/{id}
{id}
with the actual ID returned from the POST request200 OK
response with the artist’s details:404 Not Found
https://localhost:7060/artists
Content-Type
application/json
{
"fullName": "John Doe",
"stageName": "JD Music",
"genre": "Rock",
"bio": "Rock artist from Seattle",
"songsReleased": 12,
"isActive": true
}
You should receive a 200 OK
response with the ID of the newly created artist
Let’s look at our table inside of Supabase
https://localhost:7060/artists/{id}
{id}
with the actual ID of the artist you want to delete200 OK
response with an empty body404 Not Found
response, confirming the deletion was successfulLet’s check on Supabase
/artists
: Creates a new artist record in Supabase/artists/{id}
: Retrieves an artist by ID/artists/{id}
: Deletes an artist by IDappsettings.Development.json
if database operations failYou’ve successfully completed this Supabase tutorial! By following along, you have:
Keep building and exploring what’s possible with .NET and Supabase! 💻🚀