Flagpool.Sdk
0.3.1
dotnet add package Flagpool.Sdk --version 0.3.1
NuGet\Install-Package Flagpool.Sdk -Version 0.3.1
<PackageReference Include="Flagpool.Sdk" Version="0.3.1" />
<PackageVersion Include="Flagpool.Sdk" Version="0.3.1" />
<PackageReference Include="Flagpool.Sdk" />
paket add Flagpool.Sdk --version 0.3.1
#r "nuget: Flagpool.Sdk, 0.3.1"
#:package Flagpool.Sdk@0.3.1
#addin nuget:?package=Flagpool.Sdk&version=0.3.1
#tool nuget:?package=Flagpool.Sdk&version=0.3.1
Flagpool C# SDK
Official C# SDK for Flagpool — feature flags with local evaluation, deterministic rollouts, encrypted target lists, and analytics.
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-id",
ApiKey = "env_production_xxx",
DecryptionKey = "tlk_xxx",
Context = new Dictionary<string, object?>
{
["userId"] = "user-123",
["email"] = "alice@example.com",
["plan"] = "pro"
}
});
await client.InitAsync();
if (client.IsEnabled("new-dashboard"))
{
// Feature is enabled for this user
}
var theme = client.GetValue("theme-color"); // "blue", "dark", etc.
client.Dispose();
Configuration
var client = new FlagpoolClient(new FlagpoolClientOptions
{
// Required
ProjectId = "your-project-id",
ApiKey = "env_production_xxx",
DecryptionKey = "tlk_xxx",
// Optional
Context = new Dictionary<string, object?> { ["userId"] = "user-123" },
PollingIntervalMs = 30000, // Polling interval (default: 30000ms)
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, // Min: 30000ms
FlushThreshold = 100,
SampleRate = 1.0 // 0.0–1.0
}
});
Evaluation Methods
IsEnabled(key, defaultValue?)
Returns true if the flag evaluates to a boolean true. Returns defaultValue (default: false) if the flag doesn't exist or isn't a boolean.
bool enabled = client.IsEnabled("feature-x");
bool fallback = client.IsEnabled("missing-flag", false); // false
GetValue(key)
Returns the evaluated variation value. Returns null if the flag doesn't exist. Never throws.
object? value = client.GetValue("theme");
// Could be: true, false, "dark", 42, null, etc.
GetVariation(key)
Alias for GetValue.
GetAllFlags()
Returns all flag values as a dictionary.
Dictionary<string, object?> flags = client.GetAllFlags();
Context
Set user context at initialization or update it later:
// At init
var client = new FlagpoolClient(new FlagpoolClientOptions
{
// ...
Context = new Dictionary<string, object?>
{
["userId"] = "user-123",
["email"] = "alice@example.com",
["plan"] = "enterprise"
}
});
// Update later (merges with existing context)
client.UpdateContext(new Dictionary<string, object?>
{
["plan"] = "free" // Overwrites "enterprise"
});
// Read current context
var ctx = client.GetContext();
Target Lists
Target lists let you target specific users by attribute values (e.g., beta testers, VIP users).
Plaintext Target Lists
Work automatically — no extra configuration needed.
Encrypted Target Lists
If encryption is enabled for your environment, you need a crypto adapter:
using System.Security.Cryptography;
using System.Text;
public class AesCryptoAdapter : ICryptoAdapter
{
public Task<string> DecryptAsync(string ciphertext, string key, string iv, string tag)
{
// Derive key with PBKDF2-SHA256 (100,000 iterations)
var salt = Encoding.UTF8.GetBytes(key.PadRight(16, '0')[..16]);
using var kdf = new Rfc2898DeriveBytes(key, salt, 100000, HashAlgorithmName.SHA256);
var derivedKey = kdf.GetBytes(32);
// Decrypt with AES-256-GCM
using var aes = new AesGcm(derivedKey, 16);
var ivBytes = Convert.FromBase64String(iv);
var cipherBytes = Convert.FromBase64String(ciphertext);
var tagBytes = Convert.FromBase64String(tag);
var plainBytes = new byte[cipherBytes.Length];
aes.Decrypt(ivBytes, cipherBytes, tagBytes, plainBytes);
return Task.FromResult(Encoding.UTF8.GetString(plainBytes));
}
public Task<EncryptResult>? EncryptAsync(string plaintext, string key) => null;
}
// Register before InitAsync
FlagpoolCrypto.SetCryptoAdapter(new AesCryptoAdapter());
var client = new FlagpoolClient(options);
await client.InitAsync();
Error: "Encrypted target lists received but no crypto adapter configured"
This warning appears when your environment has encryption enabled but no ICryptoAdapter is registered. Flags without target list rules will still evaluate correctly. Only inTargetList / notInTargetList rules are affected.
To fix: Register a crypto adapter as shown above before calling InitAsync().
Analytics
Opt-in evaluation analytics — fire-and-forget, never blocks flag evaluation.
var client = new FlagpoolClient(new FlagpoolClientOptions
{
// ...
Analytics = new AnalyticsConfig
{
Enabled = true,
FlushIntervalMs = 60000, // Flush every 60s (minimum: 30s)
FlushThreshold = 100, // Flush when buffer reaches 100 hits
SampleRate = 1.0 // Track 100% of evaluations
}
});
// Check analytics state
var state = client.GetAnalyticsState();
Console.WriteLine($"Buffer: {state?.BufferSize}, Flushed: {state?.TotalFlushes}");
// Manual flush
client.FlushAnalytics();
Analytics are automatically flushed on process exit.
Real-Time Updates (Polling)
Enable polling to automatically refresh flags:
var client = new FlagpoolClient(new FlagpoolClientOptions
{
// ...
Streaming = true,
PollingIntervalMs = 30000 // Every 30 seconds
});
await client.InitAsync();
// Listen for changes
var unsubscribe = client.OnChange((flagKey, newValue) =>
{
Console.WriteLine($"Flag changed: {flagKey} = {newValue}");
});
// Later: stop listening
unsubscribe();
Debugging
// Get all flags with their evaluation state
var flagStates = client.GetAllFlagsWithState();
foreach (var (key, state) in flagStates)
{
Console.WriteLine($"{key}: value={state.Value}, evaluated={state.Evaluated}");
}
ASP.NET Core Integration
Register as a singleton service:
// 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 or service
public class FeatureController : ControllerBase
{
private readonly FlagpoolClient _flags;
public FeatureController(FlagpoolClient flags) => _flags = flags;
[HttpGet("dashboard")]
public IActionResult GetDashboard()
{
// Update context per-request
_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
using var client = new FlagpoolClient(options);
await client.InitAsync();
// Automatically disposed at end of scope
Missing Flags
Accessing a flag that doesn't exist is safe and never throws:
client.IsEnabled("nonexistent"); // false
client.GetValue("nonexistent"); // null
Supported Platforms
| Framework | Status |
|---|---|
| .NET 6.0 | ✅ Supported |
| .NET 8.0 | ✅ Supported |
| .NET 10.0 | ✅ Supported |
License
MIT — see LICENSE for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
-
net6.0
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.