mirror of
https://github.com/supabase/supabase.git
synced 2026-10-15 06:09:08 +03:00
Revert "docs: add introduction blog post for .NET SDK" (#51624)
Reverts supabase/supabase#50209
This commit is contained in:
3 files changed
-253
No files matched your search
@@ -1,253 +0,0 @@
|
||||
---
|
||||
title: 'Getting started with the Supabase .NET SDK'
|
||||
description: 'How to set up and use the Supabase C# client in .NET, for ASP.NET Core, Console Apps, Desktop, Unity and Mobile.'
|
||||
author: guillaume_faas
|
||||
date: '2026-10-26'
|
||||
categories:
|
||||
- developers
|
||||
tags:
|
||||
- dotnet
|
||||
- csharp
|
||||
- sdk
|
||||
imgSocial: '2026-10-26-getting-started-with-the-supabase-dotnet-sdk/og.png'
|
||||
imgThumb: '2026-10-26-getting-started-with-the-supabase-dotnet-sdk/thumb.png'
|
||||
toc_depth: 3
|
||||
---
|
||||
|
||||
The Supabase .NET SDK is a C# client for your Supabase project.
|
||||
It gives you Auth, Database, Storage, Realtime, and Edge Functions behind one API and handles the communication with the Supabase Platform.
|
||||
|
||||
Version `8.0.0` has been released, along with a new `Supabase.Extensions.DependencyInjection` package.
|
||||
This post covers how to set the client up, and then walk through basic operations.
|
||||
|
||||
## What changed in `v8.0.0`
|
||||
|
||||
If you are coming from a previous major version, a few things moved.
|
||||
You do not need all the details to follow this tutorial, but they are worth knowing:
|
||||
|
||||
- Serialization moved from Newtonsoft.Json to `System.Text.Json`. Custom converters and `[JsonProperty]` attributes need their `System.Text.Json` equivalents.
|
||||
- Every service client now accepts an injectable `HttpClient` and supports opt-in retry with backoff.
|
||||
- There is a new dependency injection package for ASP.NET Core, covered below.
|
||||
- Packages target .NET Standard 2.1. That drops .NET Framework, which tops out at .NET Standard 2.0, so you need .NET Core 3.0+ or .NET 5+.
|
||||
|
||||
If you want to see the full list of changes, check the [release notes](https://github.com/supabase/supabase-csharp/releases/tag/v8.0.0).
|
||||
The [migration guide](https://github.com/supabase/supabase-csharp/blob/master/docs/migrations/v8.0.0.md) lists every breaking change you may encounter and how to handle them.
|
||||
|
||||
## Install the package
|
||||
|
||||
Add the meta-package to your project.
|
||||
It brings in all five service packages (Auth, Postgrest, Storage, Realtime, and Functions):
|
||||
|
||||
```sh
|
||||
dotnet add package Supabase
|
||||
```
|
||||
|
||||
If you only need one service, reference it on its own instead, for example `Supabase.Gotrue` for Auth or `Supabase.Postgrest` for the database.
|
||||
|
||||
## Define a model
|
||||
|
||||
The SDK maps a table to a C# class.
|
||||
A model derives from `BaseModel` and uses attributes to link its properties to columns.
|
||||
|
||||
Here is a `todos` table that we will use in upcoming examples, with `id`, `task`, and `is_complete`:
|
||||
|
||||
```c#
|
||||
using Supabase.Postgrest.Attributes;
|
||||
using Supabase.Postgrest.Models;
|
||||
|
||||
[Table("todos")]
|
||||
public class Todo : BaseModel
|
||||
{
|
||||
[PrimaryKey("id")]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("task")]
|
||||
public string Task { get; set; }
|
||||
|
||||
[Column("is_complete")]
|
||||
public bool IsComplete { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
## Set up the client
|
||||
|
||||
### ASP.NET Core
|
||||
|
||||
Install the dependency injection package:
|
||||
|
||||
```sh
|
||||
dotnet add package Supabase.Extensions.DependencyInjection
|
||||
```
|
||||
|
||||
Register the client in `Program.cs`:
|
||||
|
||||
```c#
|
||||
using Supabase.Core.Http;
|
||||
using Supabase.Extensions.DependencyInjection;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
builder.Services.AddSupabase(
|
||||
supabaseUrl: builder.Configuration["Supabase:Url"]!,
|
||||
supabaseKey: builder.Configuration["Supabase:Key"]!,
|
||||
configureOptions: options =>
|
||||
{
|
||||
options.AutoConnectRealtime = true;
|
||||
options.PostgrestRetry = new RetryOptions { MaxRetries = 3 };
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
```
|
||||
|
||||
`AddSupabase` registers the `Supabase.Client` as a scoped service, so you can inject it wherever you need: a minimal API endpoint, a controller, or your own service.
|
||||
|
||||
```c#
|
||||
using Supabase;
|
||||
|
||||
public class TodoService(Client supabase)
|
||||
{
|
||||
public async Task<List<Todo>> GetOpen()
|
||||
{
|
||||
var result = await supabase
|
||||
.From<Todo>()
|
||||
.Where(t => t.IsComplete == false)
|
||||
.Get();
|
||||
return result.Models;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
It also registers each sub-client on its own (`IPostgrestClient`, `IGotrueClient<User, Session>`, `IStorageClient<Bucket, FileObject>`, `IFunctionsClient`, `IRealtimeClient<RealtimeSocket, RealtimeChannel>`), so a class that touches one service can depend on that alone.
|
||||
|
||||
We built this extension to make it easy for you to setup the client, rather than having to wire it up yourself.
|
||||
A `Supabase.Client` builds its own `HttpClient` when you construct it. If you register as scoped or transient, every resolution creates a fresh `HttpClient` (and a fresh socket), which will exhausts the connection pool under load.
|
||||
`AddSupabase` wires the client through `IHttpClientFactory` so the handler is pooled and reused.
|
||||
To keep this consistent, it replaces any `HttpClient` you pass through `configureOptions`; your proxy, retry, Realtime, and other options still apply.
|
||||
|
||||
### Other apps
|
||||
|
||||
Outside ASP.NET Core, in Console apps, Desktop, Mobile, or Unity, construct the client yourself and initialize it once:
|
||||
|
||||
```c#
|
||||
using Supabase;
|
||||
|
||||
var url = Environment.GetEnvironmentVariable("SUPABASE_URL")!;
|
||||
var key = Environment.GetEnvironmentVariable("SUPABASE_KEY")!;
|
||||
|
||||
var options = new SupabaseOptions
|
||||
{
|
||||
AutoRefreshToken = true,
|
||||
AutoConnectRealtime = true,
|
||||
};
|
||||
|
||||
var supabase = new Client(url, key, options);
|
||||
await supabase.InitializeAsync();
|
||||
```
|
||||
|
||||
`InitializeAsync` restores a saved session and, with `AutoConnectRealtime` on, opens the Realtime connection.
|
||||
The default session handler does not store anything, so to restore a sign-in after a restart, set `SupabaseOptions.SessionHandler` to your own implementation that saves and loads the session.
|
||||
Create the client once and reuse it in the app.
|
||||
A new client per operation means a new `HttpClient` each time, which is the same problem the DI package solves on the server.
|
||||
|
||||
## Run the common operations
|
||||
|
||||
The examples below use a `supabase` variable, which is a `Supabase.Client` instance.
|
||||
|
||||
### Query rows
|
||||
|
||||
`From<T>()` opens a query on the table mapped by `T`.
|
||||
You can then filter using `Where` and then call `Get` to execute the query.
|
||||
|
||||
`Get` returns a `ModeledResponse<T>`, and you can find the rows in `Models`:
|
||||
|
||||
```c#
|
||||
ModeledResponse<Todo> result = await supabase
|
||||
.From<Todo>()
|
||||
.Where(t => t.IsComplete == false)
|
||||
.Get();
|
||||
List<Todo> todos = result.Models;
|
||||
```
|
||||
|
||||
### Insert
|
||||
|
||||
`Insert` writes a single model or a list:
|
||||
|
||||
```c#
|
||||
await supabase.From<Todo>().Insert(new Todo { Task = "Write the launch notes", IsComplete = false });
|
||||
```
|
||||
|
||||
### Update and delete
|
||||
|
||||
There are two ways to update an entity, and both are valid.
|
||||
It simply depends on whether you already have the row in hand.
|
||||
|
||||
If you already retrieved a model, change its properties and call `Update` on it.
|
||||
A row returned from `Get` carries its own identity, so it knows which record to write:
|
||||
|
||||
```c#
|
||||
var result = await supabase.From<Todo>().Where(t => t.Id == 1).Get();
|
||||
var todo = result.Models.First();
|
||||
|
||||
todo.IsComplete = true;
|
||||
await todo.Update<Todo>();
|
||||
|
||||
await todo.Delete<Todo>();
|
||||
```
|
||||
|
||||
If you don't have a model, you can use the query builder which saves you a `Get` query.
|
||||
Set the new values, filter the rows, and run it:
|
||||
|
||||
```c#
|
||||
await supabase
|
||||
.From<Todo>()
|
||||
.Set(t => t.IsComplete, true)
|
||||
.Where(t => t.IsComplete == false)
|
||||
.Update();
|
||||
|
||||
await supabase
|
||||
.From<Todo>()
|
||||
.Where(t => t.IsComplete == true)
|
||||
.Delete();
|
||||
```
|
||||
|
||||
> While this looks very familiar to how Entity Framework is built, it does not behave the same.
|
||||
> There is no `DbContext`, no change tracker, and no `SaveChanges`.
|
||||
> Changing a property on a model does nothing until you call `Update`, and each call is its own HTTP request.
|
||||
|
||||
### Authenticate a user
|
||||
|
||||
Authentication lives on `supabase.Auth`.
|
||||
Sign a user up and in with email and password:
|
||||
|
||||
```c#
|
||||
await supabase.Auth.SignUp("maria.garcia@example.com", "a-secure-password");
|
||||
|
||||
var session = await supabase.Auth.SignIn("maria.garcia@example.com", "a-secure-password");
|
||||
```
|
||||
|
||||
With `AutoRefreshToken` enabled, the client refreshes the access token before it expires and attaches it to your database and Storage calls, so Row-Level-Security applies to the signed-in user.
|
||||
The same `supabase.Auth` surface covers OAuth, magic links, phone, and SSO.
|
||||
|
||||
### Upload a file
|
||||
|
||||
```c#
|
||||
await supabase.Storage
|
||||
.From("avatars")
|
||||
.Upload("./local/photo.png", "maria/photo.png");
|
||||
```
|
||||
|
||||
## A note on keys
|
||||
|
||||
Version `8.0.0` added the new publishable and secret API keys, alongside the existing anon and service keys.
|
||||
|
||||
Use a publishable or anon key in anything that ships to users.
|
||||
Keep secret and service keys on the server.
|
||||
A service key bypasses Row Level Security, so it does not belong in a client app.
|
||||
When you need that level of access, use a separate client for it.
|
||||
|
||||
## Next steps
|
||||
|
||||
You now have a client set up and can run queries, auth, and Storage from .NET. From here:
|
||||
|
||||
- Browse the [C# reference](https://supabase.com/docs/reference/csharp/introduction) for the full API.
|
||||
- Read the [DependencyInjection package README](https://github.com/supabase/supabase-csharp/tree/master/packages/extensions/DependencyInjection) for the ASP.NET Core details.
|
||||
- Check the [SDK repository](https://github.com/supabase/supabase-csharp) for examples and the changelog.
|
||||
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 55 KiB |
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 27 KiB |
Reference in new issue
Block a user