Feature Flags In ASP.NET Core

Introduction

Feature flags allow toggling multiple features of an application without having to redeploy the application. One or more feature flags can be defined declaratively as part of the application’s config file that can control feature availability. Feature flag is part of a broader concept of feature management. Feature management provides additional functionality like filtering feature availability based on user groups, devices etc., caching feature flags and managing their states. In this article, we will focus on implementing feature flags using ASP.NET Core feature management package.

Setup

Consider you have a simple ASP.NET 6 MVC application for creating a todo list. To keep this article focused on the subject, I will omit the steps for creating such application. Typically, the application would be capable of adding new todo items to a list of todos and displaying them on the screen.

To work with ASP.NET Core feature management, add Microsoft.FeatureManagement.AspNetCore nuget package to the application. Add the feature management service to the application inside Program.cs

using Microsoft.FeatureManagement;

namespace FeatureFlagDemo;

public class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);
        // Add services to the container.
        ...
        builder.Services.AddFeatureManagement();
        ...
        var app = builder.Build();
        ...
    }
}

Adding feature flags to the configuration

We will expose two feature flags – one for enabling edit of the todo item and another for enabling delete of the todo item. Add the feature flags to the appsettings.json file under FeatureManagement section as follows

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "FeatureManagement": {
    "Edit": false,
    "Delete": false
  },
  "AllowedHosts": "*"
}

Note both the features are disabled in the configuration file.

FeatureGate attribute

To enable the feature flags at controller or action level, we can use the FeatureGate attribute as shown below.

[HttpGet]
[FeatureGate("Edit")]
public ActionResult Edit(int id)
{
    ...
}

[HttpPost]
[FeatureGate("Edit")]
[ValidateAntiForgeryToken]
public ActionResult Edit(int id, TodoItem todoItem)
{
    ...
}

Applying the attribute for all actions related to the Edit feature will ensure that the actions are available only when the Edit feature flag is enabled. 

Add similar code for handling Delete feature.

[HttpGet]
[FeatureGate("Delete")]
public ActionResult Delete(int id)
{
    ...
}

[HttpPost]
[FeatureGate("Delete")]
[ValidateAntiForgeryToken]
public ActionResult Delete(int id, TodoItem todoItem)
{
    ...
}

Note: Part of code is omitted for brevity and to remain focused on the topic. In production scenarios, consider appropriate measures for implementing the feature including security, performance etc.

<feature> tag helper

The <feature> tag can be used to conditionally render text on razor views depending upon the state of feature flags. Import the feature management tag helpers inside the _ViewImports.cshtml file.

@using FeatureFlagDemo
@using FeatureFlagDemo.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Microsoft.FeatureManagement.AspNetCore

Inside razor view, use the <feature> tag as follows to conditionally render Edit and Delete options based on the state of their respective feature flags.

<feature name="Edit"><a asp-action="Edit" asp-route-id="@item.Id">Edit</a></feature> 
<feature name="Delete"><a asp-action="Delete" asp-route-id="@item.Id">Delete</a></feature>

Toggling feature flags and testing

Initially both the feature flags are disabled. Upon running the application, none of the Actions (Edit / Delete) are visible on the razor view.

Enable Edit feature by toggling the Edit feature flag in the appsettings.json file

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "FeatureManagement": {
    "Edit": true,
    "Delete": false
  },
  "AllowedHosts": "*"
}

Refresh the page and you should be able to see Edit feature enabled. Upon clicking edit link you can also confirm that the actions related to edit feature are being executed as per the implementation.

Enable Delete feature by toggling the Delete feature flag in the appsettings.json file

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "FeatureManagement": {
    "Edit": true,
    "Delete": true
  },
  "AllowedHosts": "*"
}

Refresh the page and you should be able to see Delete feature enabled. Upon clicking delete link you can also confirm that the actions related to delete feature are being executed as per the implementation.

Conclusion

Feature flags come in handy when you want to enable or disable application functionality without redeploying the code. The feature management package has additional functionalities that can be helpful in scenarios where you want to gradually introduce a feature into production and respond swiftly by disabling the feature in case of major errors in functionality.

References

  • https://docs.microsoft.com/en-us/azure/azure-app-configuration/concept-feature-management
  • https://docs.microsoft.com/en-us/azure/azure-app-configuration/use-feature-flags-dotnet-core