You are on page 1of 8

Featurify - User Specific Feature Flags in ASP.N... https://www.codeproject.com/Articles/1252747/...

Articles » Web Development » ASP.NET » General

Featurify - User Specific Feature Flags in ASP.NET


Core 2.0+ MVC Applications
Karthik. A, 17 Jul 2018

User specific implementation of feature flags, which can be used to roll out features targeting specific users without
doing multiple releases

GitHub Link For Featurify


GitHub Link For Featurify samples
NuGet Page for Featurify

What is Featurify?
Featurify is an implementation of feature flags that's super easy to setup and use. It intends to solve one and only one
issue where feature flags are user specific. Given this, there is absolutely no dependence on the application settings for
the MVC application in question.

Background
Featurify is designed to be light weight and easily integrate with .NET Core 2.0+ web applications. This is intended to be
one part of a two piece puzzle. If you are interested in simple application settings based feature flags, this library is not
for you! There are a number of other excellent options for that purpose and they are listed in the last section of this
article.

First part of this puzzle is to implement the user specific features at the application level. Second part of the puzzle is to
design a user interface that would help administrators to define various features and also tie them to users.

The need for this came up for one of the projects I am currently working on to selectively roll out features. There is
already a service offering that provides this (feature flags as a service) called launch darkly (docs). But there is one
catch - it's not free! The "not free" part led to the creation of this package where the same could be achieved with
minimal effort. Of course, it's not as extensive as launch darkly, in order to satisfy the criteria of "being simple".

First Part of the Puzzle


The first part of the puzzle almost exclusively deals with how featurely is put into use. So the feature flag settings for
users are dynamically generated based on a few simple steps. But in the next section, I will delve into replacing this
simplistic implementation of meta data generation with a more real life approach. So let's get started!

1 of 8 01/08/2018 11:37
Featurify - User Specific Feature Flags in ASP.N... https://www.codeproject.com/Articles/1252747/...

Setting up the Project


In order to demonstrate featurify, I am going to use .NET identity framework template. To create a project that uses the
identity framework, follow the steps given below:

1. Choose ASP.NET Core Web Application

2. Click the "Change Authentication" button:

3. Choose the "Individual User Accounts" option:

2 of 8 01/08/2018 11:37
Featurify - User Specific Feature Flags in ASP.N... https://www.codeproject.com/Articles/1252747/...

4. Open the command prompt in the root folder for the project, run the following command:

With the project created, the first step in adding feature flags to your application is to add the Featurify
nuget package using the nuget package manager or the package manager console.

The snippets given below are from one of the sample projects for featurify and you can view it online here.

> Install-Package Featurify

This command when entered in the package manager console would add the latest version (1.0.1) to the current project.

3 of 8 01/08/2018 11:37
Featurify - User Specific Feature Flags in ASP.N... https://www.codeproject.com/Articles/1252747/...

Infrastructure Classes
In order to implement feature flags in your project, all you need is two classes that implement certain interfaces. With this
done, you can use one of the IServiceCollection based extensions to put them into use.

The first class that you have to define is something that will help featurify identify the id for the user currently logged in.
This can be literally anything, a guid, an email address or anything that would uniquely identify the logged in user. This
class has to implement the IUserInfoStrategy interface. For a project based on the .NET identity framework,
the user identifying information is part of the logged in user's claims. And more specifically, the claim with type
ClaimTyes.Name contains the email address for the logged in user. For the sake of simplicity, we will use this as
the user's unique id. Here is the implementation of this class:

public class IdentityUserInfoStrategy : IUserInfoStrategy


{
private readonly IHttpContextAccessor accessor;

public IdentityUserInfoStrategy(IHttpContextAccessor accessor)


{
this.accessor = accessor;
}

public async Task<string> GetCurrentUserId()


{
var claims = accessor.HttpContext.User.Claims.ToList();
var claim = claims.Single(c => c.Type == ClaimTypes.Name);
await Task.CompletedTask;
return claim.Value;
}
}

The next step in defining the classes as part of the infrastructure requirement is to define a class that would act as the
one that would provide the feature flag metadata based on the user id and the feature name. The only requirement is
that it should implement the IToggleMetadata interface, as shown below:

public class ToggleMetadata : IToggleMetadata


{
public string Name { get; set; }
public bool Value { get; set; }
public string UserId { get; set; }
}

The next step is to define the class that provides method(s) required to take in the feature name and the user id to return
the corresponding metadata. This class should implement the IToggleMetadataFinder interface as shown
below. Before that, you might wonder how the feature name is going to be passed, we will get to that soon!

public class UserBasedToggleMetadataFinder : IToggleMetadataFinder


{
public async Task<IToggleMetadata> FindToggleStatus(string featureName, string
userId)
{
var required = toggleMetadatas.SingleOrDefault(t => t.Name == featureName &&
t.UserId == userId);
await Task.CompletedTask;
return required;
}

private static List<ToggleMetadata> toggleMetadatas = new List<ToggleMetadata>


{
new ToggleMetadata { Name = "Featurify.ImportFeature", Value = true,
UserId = "john.doe@company.com" },
new ToggleMetadata { Name = "Featurify.ExportFeature", Value = false,

4 of 8 01/08/2018 11:37
Featurify - User Specific Feature Flags in ASP.N... https://www.codeproject.com/Articles/1252747/...

UserId = "john.doe@company.com" },
new ToggleMetadata { Name = "Featurify.EmailFeature", Value = true,
UserId = "john.doe@company.com" }
};
}

If you notice, a local List<ToggleMetadata> is being used as the source for the metadata, since the emphasis
on this article is to demonstrate featurify. In a real life implementation, you can provide a page where an administrator
can go and choose the user and a feature to decide the Value. Let me take this opportunity to point out the Name
property in the entries listed in the snippet above - Featurify.{feature-name}. Soon, I will explain how
these things come together!

With this class, all the necessary infrastructure classes are ready. We can now use the AddFeaturify fluent
extension to add featurify to our .NET Core MVC application.

public void ConfigureServices(IServiceCollection services)


{
// ...

services.AddFeaturify<UserBasedToggleMetadataFinder, IdentityUserInfoStrategy>
(options =>
{
options.AnyUserVerifier = "*";
options.UseStrict = false;
});

services.AddMvc();
}

Again, it's pretty straight forward - I am using the AddFeaturify extension on IServiceCollection by
passing the types for the metadata finder and user identification strategy. You also have to pass an options object
that has 2 properties. AnyUserVerifier property identifies the string that will be used to identify if a certain
feature is enabled for all the users (irrespective of the id returned by the IdentityUserInfoStrategy). The
second property is UseStrict which indicates if an exception should be thrown if the feature metadata is not found
for a user. So, if it is set to true and no metadata has been identified for the logged in user, an exception gets thrown.

With the last step, we are all set to use featurify to implement feature flags! I am going to demonstrate this with the help
of 3 features we want to expose selectively, based on the logged in user - an import feature, an export feature and an
email feature. In order to define these features, all you have to do is create the following classes. Note that all of these
classes implement the IFeatureToggle interface.

public class ImportFeature : IFeatureToggle


{
}

public class ExportFeature : IFeatureToggle


{
}

public class EmailFeature : IFeatureToggle


{
}

Let's now see how all of these things tie together! There are two possible ways to put featurify into use. I am going to
elaborate them one by one:

Straight from the View


The first step is to add the using statements required. The next step is to inject the IFeaturifyServer in the
view. Finally, use the class that corresponds to the feature to selectively expose it to the logged in user. The code
snippet given below illustrates the same:

5 of 8 01/08/2018 11:37
Featurify - User Specific Feature Flags in ASP.N... https://www.codeproject.com/Articles/1252747/...

@using Featurify
@using Featurify.Contracts
@using AspNetIdentityWithFeaturify.Features

@inject IFeaturifyServer Featurify

<strong>ImportFeature</strong>: Enabled

@if (await Featurify.Is<ImportFeature>().Enabled())


{
<button class="btn btn-success"> Import Users</button>
}
else
{
<button class="btn btn-danger" disabled="disabled"> Import Users</button>
}

You can also move the using statements to your _ViewImports.cshtml file so that it does not have to be present in
every view. After the using statements is the @inject line where I inject the featurify server that will let me verify if
a feature is enabled for the user currently logged in. There are a couple of ways the injected IFeaturifyServer
can be used. If you do not mind verbosity, you can use the first method shown above. Here, I am using the
Is<IFeatureToggle>() extension to indicate the feature I am querying for after which I call the Enabled()
method to get the state based on the logged in user.

A number of things come together in order to make this work. They are:

1. The logged in user id is returned by the IdentityUserInfoStrategy.GetCurrentUserId


method
2. Using the static class used during the Is<T> method call, the feature name is derived as
Featurify.ImportFeature (In the next section, I will explain how this can be customized
3. Using the user id and the feature name from step (1) and (2),
UserBasedToggleMetadataFinder.FindToggleStatus method is used to identify the
metadata.

Using all of this information (and the options passed during the initial setup), the featurify server deduces the final status
of the feature for the user and returns it to the view.

You can also keep things simple by calling the Enabled<T>() method of the featurify server, as shown below:

@using Featurify
@using Featurify.Contracts
@using AspNetIdentityWithFeaturify.Features

@inject IFeaturifyServer Featurify

<strong>ImportFeature</strong>: Enabled

@if (await Featurify.Enabled<ImportFeature>())


{
<button class="btn btn-success"> Import Users</button>
}
else
{
<button class="btn btn-danger" disabled="disabled"> Import Users</button>
}

From the Controller


You can also inject the featurify server in a controller (obviously!) to achieve the same effect as shown below:

[Authorize]

6 of 8 01/08/2018 11:37
Featurify - User Specific Feature Flags in ASP.N... https://www.codeproject.com/Articles/1252747/...

public class HomeController : Controller


{
private readonly IFeaturifyServer server;

public HomeController(IFeaturifyServer server)


{
this.server = server;
}

public async Task<IActionResult> Contact()


{
var model = new ContactViewModel
{
CanImport = await server.Is<ImportFeature>().Enabled()
};
return View(model);
}
}

In this case, I am using the IFeaturifyServer injected in the constructor to identify if the ImportFeature
is enabled and set the result in a model property. This property can now be used in the view to display the feature
selectively.

Customizing Feature Name Generation


If you recall the UserBasedToggleMetadataFinder class has a private
List<ToggleMetadata> to provide the metadata information for various users. In this, the feature name
specified follows the format Featurify.{feature-name}. This is the default and can be customized to match your
requirements. To do this, you have to create a class that implements the IFeatureNameTransformer interface
as part of the infrastructure classes and specify this during the call to AddFeaturify, as illustrated below:

public class CustomNameTransformer : IFeatureNameTransformer


{
public string TransformFeatureName(string featureName)
{
return $"MyProduct.{featureName}";
}
}

Consider the CustomNameTransformer. Here, the TransformFeatureName method returns the


customized feature name. Now that this class is available, I am going to specify this as part of the AddFeaturify
call.

public void ConfigureServices(IServiceCollection services)


{
// ...

services.AddFeaturify<UserBasedToggleMetadataFinder,
IdentityUserInfoStrategy,
CustomNameTransformer>(options =>
{
options.AnyUserVerifier = "*";
options.UseStrict = false;
});

services.AddMvc();
}

7 of 8 01/08/2018 11:37
Featurify - User Specific Feature Flags in ASP.N... https://www.codeproject.com/Articles/1252747/...

Implementations Based on Application Settings


This site lists various implementations of feature flags for various languages
This is the implementation that is most active (FeatureToggle library)
This repository has an implementation of feature flags and also lists various other implementations of feature
flags in .NET.

Credits
Feature Toggle - For the inspiration to eliminate magic strings (https://github.com/jason-roberts/FeatureToggle)

Conclusion
The "second" part of the puzzle, designing the user interface is not covered in this article since it's kind of out of scope
for featurify. But it should be simple straight forward, since all that is needed is a page to manage features and a page to
link a feature to a user and a page to list them. Any feedback/ comments are welcome. Thanks for reading!

License
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author


Karthik. A
Software Developer (Senior)
United States

Just another passionate software developer!

Some of the contributions to the open source world - a blog engine written in MVC 4 - sBlog.Net. Check it out here.
For the codeproject article regarding sBlog.Net click here!

(Figuring out this section!)

Comments and Discussions


2 messages have been posted for this article Visit https://www.codeproject.com/Articles/1252747/Featurify-User-
Specific-Feature-Flags-in-ASP-NET-C to post and view comments on this article, or click here to get a print view with
messages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile Article Copyright 2018 by Karthik. A
Web01-2016 | 2.8.180728.1 | Last Updated 17 Jul 2018 Everything else Copyright © CodeProject, 1999-2018

8 of 8 01/08/2018 11:37

You might also like