IFeatureManager из package Microsoft.FeatureManagement управляет feature flags в .NET.
Он позволяет выбирать нужную ветку logic во время работы application.
Где полезны Feature Flags
-
Временно включить или быстро отключить feature, например во время new release или hotfix.
-
Отключить проблемную functionality во время failures.
-
Запускать A/B tests.
-
Поддерживать временные scenarios, например promotions.
Как это работает
Зарегистрируйте Feature Management в dependency injection container и добавьте filters, если нужно. Например, TimeWindowFilter activates flag только в specific time range.
using Microsoft.FeatureManagement;
using Microsoft.FeatureManagement.FeatureFilters;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddFeatureManagement()
// If you need a time window filter, add the following line
.AddFeatureFilter<TimeWindowFilter>();
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new()
{
Title = "Feature Flags Demo API",
Version = "v1"
});
});
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.MapControllers();
app.Run();
Настраиваем flags в appsettings.json
Задайте values feature flags в appsettings.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"FeatureManagement": {
"NewDashboard": true,
"HolidayPromo": {
"EnabledFor": [
{
"Name": "TimeWindow",
"Parameters": {
"Start": "2024-12-01T00:00:00Z",
"End": "2025-12-31T23:59:59Z"
}
}
]
}
}
}
Проверяем flag через IFeatureManager
Проверяйте state flag, injected IFeatureManager и вызывая IsEnabledAsync:
using Microsoft.AspNetCore.Mvc;
using Microsoft.FeatureManagement;
namespace FeatureFlagsDemo.Api.Controllers;
[ApiController]
[Route("api/[controller]")]
public class DashboardController(IFeatureManager featureManager) : ControllerBase
{
[HttpGet]
public async Task<IActionResult> GetDashboard()
{
var useNewDashboard =
await featureManager.IsEnabledAsync("NewDashboard");
if (useNewDashboard)
{
return Ok(new
{
Version = "New",
Data = GetNewDashboardData(),
});
}
return Ok(new
{
Version = "Legacy",
Data = GetLegacyDashboardData(),
});
}
[HttpGet("promo")]
public async Task<IActionResult> GetHolidayPromo()
{
if (!await featureManager.IsEnabledAsync("HolidayPromo"))
{
return Ok(new { Message = "No active promotions" });
}
return Ok(new
{
Message = "Holiday Special Offer!",
Discount = "50% OFF",
ValidUntil = "December 31, 2025",
PromoCode = "HOLIDAY2025"
});
}
private static object GetNewDashboardData() => new
{
Charts = new[]
{
new { Name = "Revenue Chart", Type = "Line", Interactive = true },
new { Name = "User Activity", Type = "Heatmap", Interactive = true },
new { Name = "Performance Metrics", Type = "Gauge", Interactive = true }
},
Layout = "Modern Grid",
Theme = "Dark Mode Available",
Features = new[]
{
"Real-time Updates",
"Custom Widgets",
"Export Options"
}
};
private static object GetLegacyDashboardData() => new
{
Charts = new[]
{
new { Name = "Basic Revenue", Type = "Bar", Interactive = false },
new { Name = "Simple Stats", Type = "Table", Interactive = false }
},
Layout = "Classic List",
Theme = "Light Only",
Features = new[] { "Static Reports" }
};
}
В результате можно менять behavior application через configuration без redeploy.
Этот подход экономит время, снижает риск release errors и дает team больше контроля над functionality прямо в production.