Skip to content

.NET SDK

FeatureBoard .NET SDK for .NET core and framework applications.

Installation

dotnet add package FeatureBoard.DotnetSdk

Setup

Create a Features model

You can either manually create your model or use the cli tool or nx plugin to generate a model from your configuration in FeatureBoard.

cli tool

Run npx @featureboard/cli login, then npx @featureboard/cli code-gen --template dotnet-api --output ./ to generate a Features.cs file in the output path or update an existing one.

Manual creation

Note that FeatureKeyName can be used here to apply the correct feature key to a property, otherwise FeatureBoard will do it’s best to convert the property to a kebab case key.

using FeatureBoard.DotnetSdk.Models;

public class WeatherFeatures : IFeatures
{
  [FeatureKeyName("weather-imperial")]
  public bool WeatherImperial { get; set; }
}

Implement the audience provider

This provides the audiences of the current user or application context. For example it could pull the roles from the User and add the audience key role-admin, or it could pull a location header which your CDN provides and have country-australia as an audience.

using FeatureBoard.DotnetSdk;

public class ClaimsAudienceProvider : IAudienceProvider
{
  public List<string> AudienceKeys { get; }

  public ClaimsAudienceProvider(IHttpContextAccessor contextAccessor)
  {
    AudienceKeys = contextAccessor.HttpContext?.User.Claims
      .Where(x => x.Type == "audience")
      .Select(x => x.Value).ToList() ?? new List<string>();
  }
}

Register the provider in program.cs with an update strategy

FeatureBoard SDKs are designed to work with different update strategies, to accommodate various application architectures.

Polling strategy (recommendeded)

This mode polls the FeatureBoard service for updates every based on the MaxAge configuration option in appsettings.json (default 30 seconds).

// Register feature board
builder.Services.AddFeatureBoard<WeatherFeatures, ClaimsAudienceProvider>()
  .WithPollingUpdateStrategy();

Request update strategy

This mode is useful for serverless applications where the VM gets paused between invocations, it will guarantee that the feature values are always up to date for the current invocation at the cost of an additional server call for every request.

// Register feature board
builder.Services.AddFeatureBoard<WeatherFeatures, ClaimsAudienceProvider>()
  .WithOnRequestUpdateStrategy();

Add middleware

// Add feature board middleware
app.UseFeatureBoard();

Add the environment key to appsettings.json

{
    ....
    "AllowedHosts": "*",
    "FeatureBoardOptions": {
        "EnvironmentApiKey": "YOUR KEY HERE",
        "MaxAge": "00:00:30" // Optional (defaults to 30 seconds)
    }
}

Usage

using FeatureBoard.DotnetSdk;
using FeatureBoardSdks.Examples.DotnetApi.Models;
using Microsoft.AspNetCore.Mvc;

namespace FeatureBoardSdks.Examples.DotnetApi.Controllers;

The FeatureBoard client can be injected into your class or controller with dependant injection and used directly to resolve features for the current users audience.

[ApiController]
[Route("[controller]")]
public class IconController : ControllerBase
{

  private readonly IFeatureBoardClient<Features> _featureBoardClient;
  private readonly IFeatureBoardClient<Features> _featureBoardClient;

  public IconController(ILogger<IconController> logger, IFeatureBoardClient<Features> featureBoardClient)
  {
    _featureBoardClient = featureBoardClient;
  }

  [HttpPut(Name = "Icons")]
  public IActionResult Put(IconUpdate update)
  {
    if (!_featureBoardClient.GetFeatureValue(features => features.AllowEdits, false))
    {
      return Unauthorized();
    }
    _repository.UpdateIcon(update)
  }
}

Or if you have generated your features model though the cli you can use the generated FeatureFilter attributes to limit access

[ApiController]
[Route("[controller]")]
public class IconController : ControllerBase
{
  private readonly IRepository _repository;

  public IconController(ILogger<IconController> logger, IRepository _repository)
  {
    _featureBoardClient = featureBoardClient;
  }

  [HttpPut(Name = "Icons")]
  [FeatureFilter(BooleanFeature.AllowEdits, false)]
  public IActionResult Put(IconUpdate update)
  {
    _repository.UpdateIcon(update)
  }
}

External State Store

You can create an external state store in the case where FeatureBoard is unavailable. To do this, implement IFeatureBoardExternalState.

using FeatureBoard.DotnetSdk.Models;
using FeatureBoard.DotnetSdk.States;

public class MyExternalState: IFeatureBoardExternalState
{
  public Task<Dictionary<string, FeatureConfiguration>> GetState(CancellationToken cancellationToken)
  {....}

  public Task UpdateState(Dictionary<string, FeatureConfiguration>? features, CancellationToken cancellationToken)
  {....}
}

Then register it in program.cs.

builder.Services.AddFeatureBoard<WeatherFeatures, QueryStringAudienceProvider>()
  .WithPollingUpdateStrategy()
  .WithExternalState<MyExternalState>();