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.