# Flagbearer for .NET

The .NET SDK for Flagbearer. Targets .NET 8 or later.

## Install

```sh
dotnet add package Flagbearer
```

## Keys

Use a server key, which starts with `fbs_`. Server keys are secret: read them
from configuration or the environment, such as `FLAGBEARER_SERVER_KEY`, and
never put them in browser code or in the repository. Browsers use client keys,
which start with `fbc_`, through [`@flagbearer/web`](/sdks/web).

## Sync at startup

Create one client per process, when the app starts, and wait for it to sync
before accepting requests:

```csharp
using Flagbearer;

var flags = new FlagbearerClient(Environment.GetEnvironmentVariable("FLAGBEARER_SERVER_KEY")!);

try
{
    using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(10));
    await flags.SyncAsync(timeout.Token);
}
catch (Exception error)
{
    // Keep starting: checks use their defaults, and the SDK retries in the background.
    Console.Error.WriteLine($"Initial Flagbearer sync failed: {error.Message}");
}
```

In ASP.NET Core, register it as a singleton and sync before the app starts
serving:

```csharp
builder.Services.AddSingleton(_ => new FlagbearerClient(
    builder.Configuration["Flagbearer:ServerKey"]!));

var app = builder.Build();
try
{
    await app.Services.GetRequiredService<FlagbearerClient>().SyncAsync();
}
catch (FlagbearerException error)
{
    app.Logger.LogWarning(error, "Initial Flagbearer sync failed");
}
```

The container disposes the client on shutdown.

## Check per request

Pass each request's user explicitly, and a default:

```csharp
app.MapGet("/search", (HttpContext context, FlagbearerClient flags) =>
{
    var user = new User(Key: context.User.FindFirst("sub")?.Value, Email: context.User.FindFirst("email")?.Value);
    var advanced = flags.IsEnabled("advanced-search", user, defaultValue: false);
    // …
});
```

The email is optional. Include it to turn flags on for testers by email.
The default is used until the client has synced, and when the flag doesn't
exist.

## Shut down

Keep the client for the life of the process, not per request. Dispose it on
shutdown:

```csharp
await flags.DisposeAsync();
```

Serverless functions should call `await flags.FlushAsync()` at the end of each
invocation.
