I’ve written about feature flagging your applications in the past. We’ve looked at services like LaunchDarkly and Microsoft Azure’s App Configuration service – full featured services that you can subscribe to, that brings about a lot of exciting features to selectively and safely light up new features in your applications. But if you don’t want to integrate with those third-party services, you can try out Microsoft’s Feature Management package. It’s free and doesn’t require any integration with any third-party services. In today’s post, let’s dig into how we can wire this up and use it.
Install and Configure
To set this up, download and install the Microsoft.FeatureManagement NuGet package.
dotnet add package Microsoft.FeatureManagement
I’ll be using this within the context of an ASP.NET application and as such, I’ll install the package that provides additional support for such applications.
dotnet add package Microsoft.FeatureManagement.AspNetCore
Once the package is installed, you can register it in your DI container like so:
using Microsoft.FeatureManagement; ... services.AddFeatureManagement();
Define Your Feature Flags
This feature management system works on the IConfiguration interface. In other words, you can add your feature flags in any of the configuration providers supported by dotnet – appsettings.json files, environment variables, secrets.json, ini files, or even your own custom implementation of IConfiguration – and then interact with those flags in your code using this FeatureManagement library.
For demonstration purposes, let’s go define a feature flag in our appsettings.json file.
{ "MySuperAwesomeFeature": false }
A feature flag, at its most elemental level is a Boolean, a true or false. A toggle. An on/off switch. Above, I’m defining such a flag, named MySuperAwesomeFeature
. The value is current set to false
, meaning that this feature should currently be disabled in the application.
Toggle an API Endpoint
Now, let’s start adding feature toggling logic within our code. Say you have a .NET web API and you want to control the availability of a particular endpoint using FeatureManagement. To do so, you can decorate your endpoint with a FeatureGate
attribute.
using Microsoft.AspNetCore.Mvc; using Microsoft.FeatureManagement.Mvc; namespace FeatureManagementExplorations.Controllers; [ApiController] [Route("[controller]")] public class TestController : ControllerBase { private static readonly string[] Summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; private readonly ILogger<TestController> _logger; public TestController(ILogger<TestController> logger) { _logger = logger; } [HttpGet("weather")] public IEnumerable<WeatherForecast> GetWeather() { return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), TemperatureC = Random.Shared.Next(-20, 55), Summary = Summaries[Random.Shared.Next(Summaries.Length)] }) .ToArray(); } [FeatureGate("MySuperAwesomeFeature")] [HttpGet("awesome")] public string GetAwesomeness() { return "You're awesome"; } }
In the Controller above, I’ve decorated the /awesome
endpoint with the FeatureGate
attribute. This attribute takes one or more flags that FeatureManagement will evaluate in sequence to determine whether or not traffic should be passed through to the respective action method. With the MySuperAwesomeFeature
flag set to false
, run your application and navigate to this endpoint.
You’ll notice that ASP.NET returns a 404 (Not Found) error. That is because this feature is currently set to off (false). Let’s go to our appsettings.json and change the value to true and re-run this request.
Other Usage
Feature flagging ability is not restricted to simply allowing and denying access to endpoints using this attribute. You can do all sorts of control flow logic within your application using this. Consider the modified version of the TestController
and its /awesome
action method, below.
using Microsoft.AspNetCore.Mvc; using Microsoft.FeatureManagement; namespace FeatureManagementExplorations.Controllers; [ApiController] [Route("[controller]")] public class TestController : ControllerBase { private readonly IFeatureManager feature; public TestController(IFeatureManager feature) { this.feature = feature; } [HttpGet("awesome")] public async Task<string> GetAwesomeness() { if (await feature.IsEnabledAsync("MySuperAwesomeFeature")) { return "You're awesome!"; } else { return "You're great!"; } } }
Here, we’re instantiating an instance of FeatureManager
via constructor injection. Since we have FeatureManagement registered in our Dependency Injection (DI) container, we can ask it to give us an instance of it by asking for IFeatureManager
within our constructor. With that in place, we can check the current value of a feature flag by using the IsEnabledAsync
method.
Conclusion
We’ve covered the basics but this library is pretty robust with other features such as Feature Filters, Time Window, Targeting and others so be sure to check out the GitHub repository for additional examples and further study.