Using Flagonic from .NET
Flagonic has no .NET SDK of its own — by design. You use the official OpenFeature .NET SDK with its official OFREP provider. Nothing in your dependencies is Flagonic-specific, so swapping flag vendors later is a config change, not a refactor.
Prerequisites
- A running Flagonic server with a flag defined — see the overview & quickstart.
- An SDK key (
fgn_sdk_…) for your project + environment. - .NET 8 or newer.
Install
dotnet add package OpenFeature
dotnet add package OpenFeature.Contrib.Providers.Ofrep
Initialize once at startup
using OpenFeature;
using OpenFeature.Contrib.Providers.Ofrep;
using OpenFeature.Model;
var options = new OfrepOptions(
Environment.GetEnvironmentVariable("FLAGONIC_URL")!); // e.g. https://flags.example.com
options.Headers.Add("Authorization",
$"Bearer {Environment.GetEnvironmentVariable("FLAGONIC_SDK_KEY")}");
await Api.Instance.SetProviderAsync(new OfrepProvider(options));
var client = Api.Instance.GetClient("checkout-service");
Evaluate flags
The evaluation context carries the targeting key (a stable subject identifier — it keeps percentage rollouts sticky) plus any attributes your rules match on:
var ctx = EvaluationContext.Builder()
.SetTargetingKey(user.Id)
.Set("plan", user.Plan)
.Build();
if (await client.GetBooleanValueAsync("new-checkout", false, ctx))
{
NewCheckout();
}
else
{
LegacyCheckout();
}
var theme = await client.GetStringValueAsync("banner-theme", "default", ctx);
var limit = await client.GetIntegerValueAsync("rate-limit", 100, ctx);
var ratio = await client.GetDoubleValueAsync("sampling-ratio", 0.1, ctx);
var config = await client.GetObjectValueAsync("checkout-config", new Value(), ctx);
Each call takes a default that is returned if the flag is missing or Flagonic is unreachable — pick the value you'd want during an outage.
Inspect why a value was served
var details = await client.GetBooleanDetailsAsync("new-checkout", false, ctx);
logger.LogInformation("value={Value} variant={Variant} reason={Reason}",
details.Value, details.Variant, details.Reason);
// reasons: TARGETING_MATCH, SPLIT, DEFAULT, STATIC, DISABLED, ERROR
Switching vendors
The provider speaks standard OFREP: point OfrepOptions at any other
OFREP-compatible backend — one line, no namespace changes.
Provider options occasionally shift between releases — if something doesn't compile,
check the dotnet-sdk-contrib
README for your installed version.