C# / .NET SDK
Use Flagpool feature flags in C# and .NET applications
The official C# SDK for Flagpool. Evaluate feature flags locally with deterministic rollouts, encrypted target lists, and automatic polling. Supports .NET 6.0, 8.0, and 10.0.
Installation
dotnet add package Flagpool.Sdk
Requirements: .NET 6.0 or later
Quick Start
using Flagpool.Sdk;
var client = new FlagpoolClient(new FlagpoolClientOptions
{
ProjectId = "your-project-uuid",
ApiKey = "your-api-key",
DecryptionKey = "your-decryption-key",
Context = new Dictionary<string, object?>
{
["userId"] = "user-123",
["email"] = "alice@example.com",
["plan"] = "pro",
},
});
await client.InitAsync();
// Boolean flag
if (client.IsEnabled("new-dashboard"))
{
ShowNewDashboard();
}
// String, number, or JSON flag
var theme = client.GetValue("theme-color"); // "blue", "dark", etc.
// Clean up when done
client.Dispose();
Configuration
var client = new FlagpoolClient(new FlagpoolClientOptions
{
// Required
ProjectId = "your-project-uuid",
ApiKey = "your-api-key",
DecryptionKey = "your-decryption-key",
// Optional
Context = new Dictionary<string, object?>
{
["userId"] = "user-123",
},
PollingIntervalMs = 30000, // Polling interval in ms (default: 30000)
Streaming = true, // Enable polling for real-time updates
UrlOverride = null, // Override CDN URL (for testing)
// Analytics (opt-in)
Analytics = new AnalyticsConfig
{
Enabled = true,
FlushIntervalMs = 60000,
FlushThreshold = 100,
SampleRate = 1.0,
},
});
| Option | Type | Required | Description |
|---|---|---|---|
ProjectId | string | Yes | Project UUID from the dashboard |
ApiKey | string | Yes | Environment-specific API key |
DecryptionKey | string | Yes | For CDN URL hashing and target list decryption |
Context | Dictionary | No | User context for targeting rules |
PollingIntervalMs | int | No | Polling interval in ms (default: 30000) |
Streaming | bool | No | Enable polling for real-time updates |
UrlOverride | string | No | Complete URL override for self-hosted setups |
Analytics | AnalyticsConfig | No | Analytics configuration (opt-in) |
API Reference
| Method | Description |
|---|---|
InitAsync() | Initialize client and fetch flags (required before evaluation) |
IsEnabled(key, defaultValue?) | Check if a boolean flag is enabled |
GetValue(key) | Get flag value (any type, returned as object?) |
GetVariation(key) | Alias for GetValue |
GetAllFlags() | Get all evaluated flag values as a dictionary |
UpdateContext(ctx) | Update user context — flags re-evaluate automatically |
OnChange(callback) | Subscribe to flag value changes; returns an unsubscribe action |
Close() | Stop polling (keeps analytics running) |
Dispose() | Full teardown — stops polling and flushes analytics |
Flag Types
Boolean Flags
if (client.IsEnabled("feature-flag"))
{
// Feature is enabled for this user
}
// With explicit default
bool enabled = client.IsEnabled("missing-flag", false); // false
String Flags
var variant = client.GetValue("button-color") as string;
// "blue" | "green" | "orange"
Number Flags
var limit = client.GetValue("rate-limit");
// 100 | 1000 | 10000
JSON Flags
var config = client.GetValue("checkout-config");
// Returns a deserialized object
Dynamic Context Updates
Update user context on the fly — flags re-evaluate automatically:
// User on free plan
Console.WriteLine(client.GetValue("max-upload-size-mb")); // 10
// User upgrades to pro
client.UpdateContext(new Dictionary<string, object?>
{
["plan"] = "pro",
});
// Instantly gets pro limits
Console.WriteLine(client.GetValue("max-upload-size-mb")); // 100
Real-Time Updates
Enable polling and listen for changes:
var unsubscribe = client.OnChange((flagKey, newValue) =>
{
Console.WriteLine($"Flag changed: {flagKey} = {newValue}");
});
// Later: stop listening
unsubscribe();
Missing Flags
Accessing a flag that doesn't exist is safe and never throws:
client.IsEnabled("nonexistent"); // false
client.GetValue("nonexistent"); // null
Framework Examples
ASP.NET Core
// Program.cs
var flagpool = new FlagpoolClient(new FlagpoolClientOptions
{
ProjectId = builder.Configuration["Flagpool:ProjectId"]!,
ApiKey = builder.Configuration["Flagpool:ApiKey"]!,
DecryptionKey = builder.Configuration["Flagpool:DecryptionKey"]!,
Streaming = true,
});
await flagpool.InitAsync();
builder.Services.AddSingleton(flagpool);
// In a controller
public class FeatureController : ControllerBase
{
private readonly FlagpoolClient _flags;
public FeatureController(FlagpoolClient flags) => _flags = flags;
[HttpGet("dashboard")]
public IActionResult GetDashboard()
{
_flags.UpdateContext(new Dictionary<string, object?>
{
["userId"] = User.FindFirst("sub")?.Value,
});
if (_flags.IsEnabled("new-dashboard"))
return Ok(new { version = "v2" });
return Ok(new { version = "v1" });
}
}
Lifecycle
// Stop polling (keeps analytics running)
client.Close();
// Full teardown (stops polling + flushes analytics)
client.Dispose();
// Or use 'using' statement for automatic cleanup
using var client = new FlagpoolClient(options);
await client.InitAsync();
// Automatically disposed at end of scope
Analytics
Track flag evaluation counts. Analytics is opt-in and disabled by default.
var client = new FlagpoolClient(new FlagpoolClientOptions
{
// ...required options
Analytics = new AnalyticsConfig
{
Enabled = true,
FlushIntervalMs = 60000,
FlushThreshold = 100,
SampleRate = 1.0,
},
});
| Option | Type | Default | Description |
|---|---|---|---|
Enabled | bool | false | Enable/disable analytics |
FlushIntervalMs | int | 60000 | Flush interval in ms (minimum: 30000) |
FlushThreshold | int | 100 | Flush after N evaluations |
SampleRate | double | 1.0 | Sample rate (0.0–1.0) |
Supported Platforms
| Framework | Status |
|---|---|
| .NET 6.0 | Supported |
| .NET 8.0 | Supported |
| .NET 10.0 | Supported |
Targeting Operators
| Operator | Description | Example |
|---|---|---|
eq | Equals | plan == "enterprise" |
neq | Not equals | plan != "free" |
in | In list | country in ["US", "CA"] |
nin | Not in list | country not in ["CN", "RU"] |
contains | String contains | email contains "@company.com" |
startsWith | String starts with | userId startsWith "admin-" |
inTargetList | In target list | userId in beta-testers |
notInTargetList | Not in target list | userId not in blocked-users |
Next Steps
- Getting Started — full setup guide
- Using Flags in Code — evaluation patterns across all SDKs