Zenmanage 1.1.0
dotnet add package Zenmanage --version 1.1.0
NuGet\Install-Package Zenmanage -Version 1.1.0
<PackageReference Include="Zenmanage" Version="1.1.0" />
<PackageVersion Include="Zenmanage" Version="1.1.0" />
<PackageReference Include="Zenmanage" />
paket add Zenmanage --version 1.1.0
#r "nuget: Zenmanage, 1.1.0"
#:package Zenmanage@1.1.0
#addin nuget:?package=Zenmanage&version=1.1.0
#tool nuget:?package=Zenmanage&version=1.1.0
Zenmanage .NET SDK
Add feature flags to your .NET applications in minutes. Control feature rollouts, A/B tests, and configuration values without deploying code.
Why Zenmanage?
- Fast local rule evaluation after rules are cached.
- Target users, organizations, and custom segments with context-aware rules.
- Roll out features safely with deterministic percentage bucketing.
- Use inline defaults or reusable defaults collections to avoid brittle code paths.
- Package layout and metadata are ready for public NuGet publishing.
Requirements
- .NET 8.0+
Installation
dotnet add package Zenmanage
Key Compatibility
- Supported in server runtime mode: server keys prefixed with
srv_ - Supported in client runtime mode: client keys prefixed with
cli_ - Not supported: mobile keys prefixed with
mob_
By default, ConfigBuilder validates for a server runtime. If you need client-key validation, call WithRuntimeEnvironment(RuntimeEnvironment.Client) explicitly.
Get Started
using Zenmanage;
var zenmanage = new Zenmanage.Zenmanage(
ConfigBuilder.Create()
.WithEnvironmentToken("srv_your_server_key_here")
.Build());
var flag = await zenmanage.Flags().SingleAsync("new-dashboard");
if (flag.IsEnabled())
{
Console.WriteLine("Render the new dashboard");
}
else
{
Console.WriteLine("Render the classic dashboard");
}
Common Use Cases
Gradual Rollouts
using Zenmanage.Contexting;
var context = Context.Single("user", "user-123", "Jane Doe");
var rolloutFlag = await zenmanage.Flags()
.WithContext(context)
.SingleAsync("beta-program");
if (rolloutFlag.IsEnabled())
{
Console.WriteLine("User is part of the beta rollout");
}
A/B Testing
using Zenmanage.Contexting;
var context = new Context(
"user",
name: "Jane Doe",
identifier: "user-123",
attributes: new[]
{
new Attribute("country", new[] { "US" }),
new Attribute("plan", new[] { "premium" })
});
var variant = await zenmanage.Flags()
.WithContext(context)
.SingleAsync("checkout-flow", "control");
Console.WriteLine($"Variant: {variant.AsString()}");
Defaults
using Zenmanage.Defaults;
var defaults = new DefaultsCollection()
.Add("new-ui", true)
.Add("api-version", "v2")
.Add("max-items", 100);
var flag = await zenmanage.Flags()
.WithDefaults(defaults)
.SingleAsync("new-ui");
Console.WriteLine(flag.IsEnabled());
Json Flags
var config = await zenmanage.Flags().SingleAsync("checkout-config", new Dictionary<string, object>
{
["maxRetries"] = 3,
["providers"] = new[] { "stripe", "paypal" }
});
var maxRetries = config.AsJson().GetProperty("maxRetries").GetInt32();
A json default can be an inline IDictionary/IEnumerable (list, array, etc.), a
System.Text.Json.JsonElement, or registered on a DefaultsCollection via
Add(key, JsonElement).
Filesystem Caching
using Zenmanage.Caching;
var sdk = new Zenmanage.Zenmanage(
ConfigBuilder.Create()
.WithEnvironmentToken("srv_your_server_key_here")
.WithCacheBackend(CacheBackend.Filesystem)
.WithCacheDirectory(Path.Combine(AppContext.BaseDirectory, ".zenmanage-cache"))
.Build());
ASP.NET Core Registration
using Zenmanage;
using Zenmanage.Caching;
builder.Services.AddSingleton(sp => new Zenmanage.Zenmanage(
ConfigBuilder.Create()
.WithEnvironmentToken(builder.Configuration["Zenmanage:EnvironmentToken"]!)
.WithCacheBackend(CacheBackend.Memory)
.Build()));
Value Types & Cross-Type Coercion
A flag's type is one of Boolean, String, Number, or Json. Each has a matching accessor (AsBool(), AsString(), AsNumber(), AsJson()), plus IsEnabled() for boolean flags specifically.
AsJson() returns the decoded value as a System.Text.Json.JsonElement, covering both JSON objects and JSON arrays.
Calling the "wrong" accessor for a flag's type never throws — it returns a safe zero value for that type instead of attempting a lossy conversion:
| Called on → Flag type ↓ | AsBool() |
AsString() |
AsNumber() |
AsJson() |
|---|---|---|---|---|
Boolean |
the bool | "true"/"false" |
1/0 |
empty array |
String |
true if non-empty |
the string | parsed number, or 0 |
empty array |
Number |
true if non-zero |
the number as a string | the number | empty array |
Json |
false |
"" |
0 |
the decoded value |
A Json flag whose decoded value isn't itself an object or array (a bare JSON scalar such as 5 or "x", which the API allows but which real flags won't normally use) makes AsJson() return an empty array too — the same safe-zero-value fallback as calling it on a non-json flag, rather than wrapping the scalar or throwing.
Default values passed to SingleAsync(key, defaultValue) or DefaultsCollection are typed from the .NET value itself: an IDictionary, an IEnumerable (excluding string), or a JsonElement holding an object/array becomes a Json-typed flag (not a stringified fallback), so AsJson() on a missing flag with such a default returns that value unchanged.
Configuration
using Zenmanage;
using Zenmanage.Caching;
var config = ConfigBuilder.Create()
.WithEnvironmentToken("srv_your_server_key_here")
.WithCacheTtl(3600)
.WithCacheBackend(CacheBackend.Memory)
.WithUsageReporting(true)
.WithApiEndpoint("https://api.zenmanage.com")
.Build();
Supported environment variables:
ZENMANAGE_ENVIRONMENT_TOKENZENMANAGE_CACHE_TTLZENMANAGE_CACHE_BACKENDZENMANAGE_CACHE_DIRZENMANAGE_ENABLE_USAGE_REPORTINGZENMANAGE_API_ENDPOINT
Running Tests
dotnet restore
dotnet test --collect:"XPlat Code Coverage"
Examples
See examples/README.md for the sample set:
simple-flags.cscontext-based-flags.csdefaults.cscaching.csab-testing.cspercentage-rollouts.csaspnet-core.cs
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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 was computed. 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. |
-
net8.0
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.2)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Zenmanage:
| Package | Downloads |
|---|---|
|
Zenmanage.AspNetCore
ASP.NET Core integration for the Zenmanage feature flag SDK. Provides dependency injection extensions and request-scoped context middleware. |
GitHub repositories
This package is not used by any popular GitHub repositories.