ASP.NET Core Feature Flag TagHelper

Releasing stuff is dangerous: you might break things, you might annoy your users or you could screw up in any number of entertaining ways.

Feature flags are a great way to get functionality into production without quite so much risk. You can release your new feature to only a small subset of your users and then roll it out once you’re happy that things aren’t on fire.

The way you define flags will depend on the requirements for roll out – sometimes a configuration setting is sufficient; sometimes you’ll need per-user settings or something more complex. That’s outside the scope of this article though – I’ll leave that part up to you.

Once you have your flags defined you want to start modifying content based on those flags. You coulds do that with a bunch of if statements but when we’re talking about Razor it can get messy fast.

Instead, wouldn’t it be nice to wrap your new stuff in a special tag?

<feature flag="MyCoolNewThing">
  <!-- cool content here -->
</feature>

Or if you want to display something only for users without the new feature?

<feature flag="MyCoolNewThing" disabled>
  Click here to enable my new cool thing!
  <button>Enable Now!</button>
</feature>

Tag Helpers make this easy!

The TagHelper Class

Tag helpers allow you to write server-side code that manipulates the DOM during the render of a Razor view. They can accept dependency-injected services (in the scope of the current request) and can access attributes and child content of their Razor element.

They are implemented by extending the TagHelper class and are used in Razor views by converting the class name to a kebab-cased equivalent. e.g. MyGreatNewTagHelper would be available via the my-great-new tag.

The class then modifies the generated DOM by overriding either the Process or ProcessAsync methods. These methods are passed context objects to allow both interrogation of the current content and modification of the output.

public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
  //...
}

Hiding Child Content

In our case, the “modification” we want is really simple: we want to optionally hide all child content. This is directly supported via the TagHelperOutput.SuppressContent() method so we can hide content with a 1 line method:

public override async Task ProcessAsync(
  TagHelperContext context, 
  TagHelperOutput output)
{
  output.SuppressContent();
}

note that we don’t need to be using the ProcessAsync variant as we have no async code yet, but we’ll be adding some shortly

Optionally Hiding Child Content

We only want to hide the child content if a feature flag is disabled, so we need to know the state of the flag. There are a lot of ways that feature flag settings could be implemented (configuration settings, per-user flags, etc.) so we are going to abstract all of that away behind an interface:

public interface IFeatureFlagProvider {
  Task<bool> IsEnabled(FeatureFlag featureFlag);
}

public enunm FeatureFlag {
  Unknown,
  MyCoolNewThing,
  AnotherAwesomeFeature,
  Etc
}

The IFeatureFlagProvider accepts an enum value identifying a feature and asynchronously returns a boolean indicating whether or not the feature is enabled. Any complexity around how you determine the availability of the feature can happily hide behind this facade.

Note: I’m using an enum to define my features but strings are a valid alternative. I prefer enums because you can find all references easily and if you’re adding new features then you’re going to be changing code anyway!

As I said above, tag helpers can accept injected dependencies so as soon as we have registered an implementation of IFeatureFlagProvider we can use it in our helper. We’re also going to add a Flag property which will be set on each instance of the tag.

public class FeatureTagHelper : TagHelper
{
  private readonly IFeatureFlagProvider _featureFlagProvider;

  public FeatureTagHelper(IFeatureFlagProvider featureFlagProvider)
  {
    _featureFlagProvider = featureFlagProvider;
  }

  public FeatureFlag Flag { get; set; }

  public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
  {
    var isFeatureEnabled = await _featureFlagProvider.IsEnabled(this.Flag);
    if (!isFeatureEnabled)
      output.SuppressContent();
  }
}

Support Disabled State

We may want to show content only when a feature is not enabled (e.g. an “enable now” message) so we want to support the inverse. One option would be to create a second tag helper but I felt like a disabled flag made more sense when in Razor:

<feature flag="FeatureName" disabled>...</feature>

To achieve this we can use the supplied TagHelperContext to look for a disabled attribute and then combine this with our isFeatureEnabled condition from earlier:

public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
    var isFeatureEnabled = await _featureFlagProvider.IsEnabled(this.Flag);
    var isTagDisabled = context.AllAttributes.Where(a => a.Name?.ToLowerInvariant() == "disabled").Any();

    var showContent = isFeatureEnabled != isTagDisabled;
    if (!showContent)
      output.SuppressOutput();
  }
}

Using the TagHelper

Now that we’ve created the tag helper we can start using it in our Razor views.

Before it becomes available we will need to add it to the project in the Views/_ViewImports.cshtml file that is created as part of the ASP.NET Core templates.

You can either add all tag helpers in your project or add each one individually.

<!-- add all in assembly MyProject -->
@addTagHelper *, MyProject
<!-- or add individually -->
@addTagHelper MyProject.TagHelpers.FeatureTagHelper, MyProject

Once that’s done you can use the new tags in any of your Razor pages or views as below:

<feature flag="MyCoolNewThing">
  <!--
    content will only be displayed if FeatureFlag.MyCoolNewThing is enabled
    for the current user
  -->
  <h1>Cool New Thing</h1>
</feature>

<feature flag="MyCoolNewThing" disabled>
  <!--
    content will only be displayed if FeatureFlag.MyCoolNewThing is disabled
    for the current user
  -->
  Click here to enable my new cool thing!
  <button>Enable Now!</button>
</feature>
Advertisements

Lightweight Bar Chart in Vanilla CSS

There are a hundred and one JavaScript charting libraries out there that can do amazing things with your data. Sometimes, though, a whole library is overkill. Libraries come at a cost and for simple charts you can often do what you need without any third party code at all.

Here’s an example of how you can create a bar chart using just HTML and CSS.

The HTML

First off we’ll need some HTML to manipulate with our CSS. You’ll probably be using server side rendering and for this example I was using Razor pages. My .cshtml looked
something like this:

<div class="chart">
  <div class="bars">
    @foreach (var point in Model.Data)
    {
    <div class="bar" style="height:@(point.ValueAsPercentOfMax)%;"></div>
    }
  </div>
  <div class="labels">
    @foreach (var point in Model.Data)
    {
    <span class="label">@point.Label</span>
    }
  </div>
</div>

…which outputs HTML like this…

<div class="chart">
  <div class="bars">
    <div class="bar" style="height:50%;"></div>
    <div class="bar" style="height:20%;"></div>
    <div class="bar" style="height:70%;"></div>
    <!-- etc -->
  </div>
  <div class="labels">
    <span class="label">Bar 1</span>
    <span class="label">Bar 2</span>
    <span class="label">Bar 3</span>
    <!-- etc -->
  </div>
</div>

One important thing to note is that we are translating our data values into %age heights on the .bar divs. Combined with some CSS this will turn these divs into the bars in our bar chart.

That’s all we need to do for the DOM but so far it doesn’t look great

plain-dom

Let’s add some styles!

The CSS

First things first: we need to be able to see the bars. At the moment the .bar divs have a %age height set but their containing element .bars has zero height. A %age of zero is zero, so no bars!

We want the bars to take up all available space above the labels so let’s turn .chart into a vertical flexbox and set the .bars to flex so they fill up anything left over from the labels.

Note: I’ve given the chart a fixed height & width, but we’ll be writing this so that it will grow or shrink to fit the available space. I’ve also given each .bar a background color so we can see where they are!

.chart {
  height: 100px;
  width: 200px;
  display: flex;
  flex-direction: column;
}

.bars {
  flex: 1;
}

.bar {
  background: red;
}

bar-height

Now the .bars container is the right height (pushing the labels to the bottom) but we still can’t see them. This time they have height but zero width.

We can get .bars to space it’s components out horizontally, then have each .bar grow to take up the available space with flex: 1. By setting all child elements of .bars to have the same flex value they will all be assigned the same share of the available space.

.bars {
  flex: 1;
  display: flex;
  flex-direction: row;
}
.bar {
  flex: 1;
  background: red;
}

horizontal-spacing

Ok, now we’re getting somewhere: we have bars! We don’t want them at the top though, so let’s set .bars to align it’s items to flex-end to get them to the bottom.

.bars {
  /* ...as above... */
  align-items: flex-end;
}

vertical-align

Better. Those labels need to line up with the columns though, so let’s apply the same horizontal flex to .labels-container. We can add some text alignment and a little padding while we’re about it.

.labels {
  display: flex;
  flex-direction: row;
}
.label {
  flex: 1;
  padding: 3px;
  text-align: center;
}

labels

Much better, but the “big red square” column style isn’t the best. Let’s give each column some padding, border and a nice background color and…

.bar {
  flex: 1;
  border-radius: 3px 3px 0 0;
  background: rgba(98, 144, 200, 1);
  border: 1px solid rgba(55, 105, 150, 1);
  border-bottom: none;
  margin: 0 18px;
}

pretty-bars

Pretty good! We just want one final touch to add a bit of polish: animation. We can make our bars grow to their full height as the page loads by animating the translateY property from 100% (i.e. entirely outside the parent element) to 0 (i.e. the desired final position).

@keyframes grow-column {
  0% {
    transform: translateY(100%);
  }
  100% {
    transform: translateY(0);
  }
}

.bars {
  /* ...as above ... */
  overflow: hidden;
}

.bar {
  /* ... as above ... */
  animation: grow-column 1s;
}

We need to set the containing .bars element to hide all overflow content; otherwise we would see the columns sliding in over the top of the labels.

animation

✨ tada! ✨ A nice looking simple bar chart at a cost of a few bytes of CSS!

Composite Pattern in .NET Core with Dependency Injection

Following on from my previous post where I implemented a decorator pattern using .NET Core dependency injection I realised that I could use the same method to create a composite pattern in a developer-friendly way.

Composite Pattern

Similar to the decorator pattern, the Composite Pattern let’s you wrap existing implementations of an interface to augment the functionality.

The difference between the two is that the decorator wraps a single instance of the interface; a composite wraps many.

interface IService {
  void DoSomething(string value);
}

class Decorator : IService {
  public Decorator(IService wrappedService) {
    //...
  }
}

class Composite : IService {
  public Composite(IEnumerable<IService> wrappedServices) {
    //...
  }
}

This is useful where you have a number of implementations of your service and you don’t want dependent classes to know whether they should call one, some or all of them.

For example, if you have a report generator that wants to send results to multiple sources you might implement several instances of IReporter:

interface IReporter {
  void Send(IReport report);
}

class ConsoleReporter : IReporter {
  public void Send(IReport report) {
    //write details to console
  }
}

class TelemetryReporter : IReporter {
  public void Send(IReport report) {
    //write stats to a telemetry service
  }
}

class EmailReporter : IReporter {
  public void Send(IReport report) {
    //send a report email to stakeholders
  }
}

Your composite reporter would construct on all other implementations of IReporter and call them in order:

class CompositeReporter : IReporter {
  private IEnumerable<IReporter> _reporters;

  public CompositeReporter(IEnumerable<IReporter> reporters) {
    _reporters = reporters;
  }

  public void Send(IReport report) {
    foreach (var reporter in _reporters)
      reporter.Send(report);
  }
}

This means that anything that needs to send a report can request a single IReporter and let the CompositeReporter worry about routing the report through the correct concrete implementations.

Default DI Behaviour

As discussed in the previous post, the default behaviour of the .NET Core Dependency Injection framework is to provide the last-registered copy of an interface, or all registered copies for an IEnumerable.

services.AddScoped<IService, ConcreteService1>();
services.AddScoped<IService, ConcreteService2>();
services.AddScoped<IService, ConcreteService3>();

//later
const service = serviceProvider.GetRequiredService<IService>();
// service is instance of ConcreteService3

const allServices = serviceProvider.GetRequiredService<IEnumerable<IService>>();
// allServices contains one instance of all 3 registered implementations

What we need is a way to register a new type to replace the existing registrations and take them in as a constructor dependency.

class Composite : IService {
  public class Composite(IEnumerable<IService> services) {
    //...
  }
}

//BAD - throws StackOverflowException when resolved!
services.AddScoped<IService, Composite>();

Unfortunately the default behaviour of the DI framework is to attempt to fulfil the request for all IService implementations with…another instance of Composite! One StackOverflowException later and we’re back to the drawing board.

How can we make this play nicely with DI?

Borrowing from the Last Post

After some digging through the ASP.NET Core source code in the last post we came up with a couple of useful helpers that we can re-use here: CreateFactory and CreateInstance.

ActivatorUtilities.CreateFactory generates a factory function to create an instance of ConcreteType from the service provider with some services provided explicitly.

var objectFactory = ActivatorUtilities.CreateFactory(
  typeof(ConcreteType), 
  new[] { typeof(IService) });

CreateInstance creates an instance of a service from a ServiceDescriptor.
We can get instances of ServiceDescriptor from the service collection and use these to create previously-registered types.

public static object CreateInstance(this IServiceProvider services, ServiceDescriptor descriptor)
{
  if (descriptor.ImplementationInstance != null)
    return descriptor.ImplementationInstance;

  if (descriptor.ImplementationFactory != null)
    return descriptor.ImplementationFactory(services);

  return ActivatorUtilities.GetServiceOrCreateInstance(services, descriptor.ImplementationType);
}

With these tools we can define our desired composite behaviour.

Extract Existing Registrations

When we register a new composite we want to

  1. Remove all existing registered services for the same interface
  2. Insert the composite implementation
  3. Pass instances of all removed implementations into the constructor of the composite

Remove Existing Registrations

IServiceCollection extends IEnumerable so we can filter it down to get the services that match the interface of the composite class.

public static void AddComposite<TInterface, TConcrete>(this IServiceCollection services)
  where TInterface : class
  where TConcrete : class, TInterface
{
  //get a list of existing registrations matching the target interface
  var wrappedDescriptors = services
    .Where(s => s.ServiceType == typeof(TInterface))
    .ToList();

  //remove each from the service collection
  foreach (var descriptor in wrappedDescriptors)
    services.Remove(descriptor);

  //...
}

We call ToList to we get a persistent list of the items and then remove them from the original collection.

Add Composite Implementation

Next up we want to insert the definition of our composite class, and we’re going to use the ActivatorUtilites helper mentioned above.

var objectFactory = ActivatorUtilities.CreateFactory(
  typeof(TConcrete),
  new[] {
    typeof(IEnumerable<TInterface>)
  });

Here we create a factory function that can be used with a service provider to resolve an instance of TConcrete (i.e. our composite class) with any parameters of type IEnumerable{TInterface} manually specified by us.

The objectFactory forms the basis of a new ServiceDescriptor to add to the collection.

var compositeDescriptor = ServiceDescriptor.Describe(
  typeof(TInterface),
  serviceProvider => (TInterface)objectFactory(serviceProvider, new [] {
    /* todo: inject original services here */
  },
  ServiceLifetime.Scoped);
);

services.Add(compositeDescriptor);

Note: in this example I have hard-coded a lifetime of Scoped for the service. We can improve on this below but it will do for now.

Inject Original Services

We still need to inject instances of the original services that we removed. We recorded their service descriptors in wrappedDescriptors and we can now combine those with the CreateInstance extension method above to populate our constructor parameter.

var compositeDescriptor = ServiceDescriptor.Describe(
  typeof(TInterface),
  serviceProvider => (TInterface)objectFactory(serviceProvider, new [] {
    wrappedDescriptors
      .Select(d => serviceProvider.CreateInstance(d))
      .Cast<TInterface>()
  },
  ServiceLifetime.Scoped);
);

Now all of the wrapped services will be created through the service provider and passed to our composite.

This approach may seem long winded but it has the advantage that any other dependencies of either the wrapped services or our composite will also be injected from the service provider with no further input from us!

Calculate Lifetime Scope

The hard-coded lifetime scope isn’t ideal, and whilst we could push the onus onto the caller to specify a scope we can do slightly better and infer it from the existing registrations.

If the composite depends on a Scoped instance then it can be either Scoped or Transient without a problem, but cannot be Singleton as it would not have access to scoped dependencies.

We can infer the maximum scope of the composite by taking the most specific scope of it’s dependencies. The ServiceLifetime enum is defined with the least specific scope (Singleton) as 0 so we can select the maximum value to get the most specific.

Pull it All Together

Combining all of the above we get the following extension method:

public static void AddComposite<TInterface, TConcrete>(this IServiceCollection services)
  where TInterface : class
  where TConcrete : class, TInterface
{
  var wrappedDescriptors = services.Where(s => s.ServiceType == typeof(TInterface)).ToList();
  foreach (var descriptor in wrappedDescriptors)
    services.Remove(descriptor);

  var objectFactory = ActivatorUtilities.CreateFactory(
    typeof(TConcrete), 
    new[] { typeof(IEnumerable<TInterface>) });

  services.Add(ServiceDescriptor.Describe(
    typeof(TInterface),
    s => (TInterface)objectFactory(s, new[] { wrappedDescriptors.Select(d => s.CreateInstance(d)).Cast<TInterface>() }),
    wrappedDescriptors.Select(d => d.Lifetime).Max())
  );
}

Now we can wrap up as many services as we want in a composite with one line

var services = new ServiceCollection();
services.AddSingleton<IReporter, ConsoleReporter>();
services.AddScoped<IReporter, TelemetryReporter>();
services.AddTransient<IReporter, EmailReporter>();

services.AddComposite<IReporter, CompositeReporter>();

Decorators in .NET Core with Dependency Injection

What is a Decorator?

Feel free to skip this section if you’re already familiar with the Decorator pattern

The Decorator Pattern allows you to add functionality to an implementation of an interface by wrapping it in another implementation. e.g.

interface IService {
  string GetValue();
}

class DbService {
  public string GetValue() => "value from DB";
}

class LoggingService {
  private readonly IService _concreteService;
  private readonly ILogger _logger;

  public LoggingService(IService concreteService, ILogger<LoggingService> logger) {
    _concreteService = concreteService;
    _logger = logger;
  }

  public string GetValue() {
    _logger.LogInformation("Getting value");
    var value = _concreteService.GetValue();
    _logger.LogInformation("Retrieved {0}", value);
    return value;
  }
}

We have a concrete implementation of an IService interface (DbService) that returns a string value. LoggingService then decorates that implementation by wrapping invocation of the concrete instance and logging entry and exit.

This pattern is very useful when you want to augment either your own or framework types with some new behaviour such as logging or exception handling.

Decorators and Dependency Injection

The dependency injection framework in .NET Core is pretty good but out-of-the-box it doesn’t support this pattern very well.

If I register 2 copies of IService then any class attempting to consume IService will receive the one that was registered last. If they try to consume an IEnumerable then they will receive all of them. This is perfectly sensible behaviour but in this case it makes life harder.

Worse, if an implementation of IService depends on an instance of IService (and is the last one registered) then we will get a StackOverflowException when we resolve it!

Ideally we would like to be able to use this pattern with dependency injection without having to put too many constraints on either the decorator or the concrete implementation.

Specifically:

  • the wrapped implementation should be able to be registered in the DI container against the same interface as the decorator. This avoids adding any requirements to the code we are decorating
  • the decorator should depend on an instance of the interface it implements. This allows decorators to be applied to other decorators or implementations and makes the decorator easily testable
  • any dependencies of either the concrete implementation or the decorator should be injected automatically

So how can we achieve all this?

Approach #1: Reference a Concrete Type

Have the decorator explicitly depend on a concrete implementation of the wrapped class.

class Decorator : IService {
  public Decorator(ConcreteService service) {}
}

public static void ConfigureServices(IServiceCollection services) {
  services.Replace(ServiceDescriptor.Scoped<IService, Decorator>());
}
  • ✅ Easy
  • ❌ Can only decorate one implementation
  • ❌ Cannot inject a mock for unit tests
  • ❌ Requires the decorated implementation to be registered against it’s concrete type – not the interface
  • ❌ Cannot take service lifetime (scoped, transient or singleton) from wrapped service

Overall, it’s not great.

Approach #2: Use a Factory Registration

Use a factory method to pass the explicit concrete type to the decorator constructor.

class Decorator : IService {
  public Decorator(IService concreteService) {}
}

public static void ConfigureServices(IServiceCollection services) {
  services.Replace(ServiceDescriptor.Scoped<IService>(s =>
    new Decorator(s.GetRequiredService<ConcreteService>())
  ));
}
  • ✅ Decorator can construct on an interface
  • ❌ Still requires decorated implementation to be registered against it’s concrete type
  • ❌ Forces you to manually maintain other dependencies for Decorator
  • ❌ Cannot take service lifetime from wrapped service

This solution is relatively neat until your Decorator class starts to gain other dependencies.

class Decorator : IService {
  public Decorator(
    IService concreteService,
    IOtherService1 anotherDependency,
    IOtherService2 yetAnotherDependency) {}
}

public static void ConfigureServices(IServiceCollection services) {
  services.Replace(ServiceDescriptor.Scoped<IService>(s =>
    new Decorator(
      s.GetRequiredService<ConcreteService>(),
      s.GetRequiresService<IOtherService1>(),
      s.GetRequiredService<IOtherService2>())
  ));
}

It’s not the end of the world but it is a bit of a headache having to manually update constructor calls when you change a signature.

This approach also fails our requirement that the wrapped implementation is not explicitly specified.

Approach #3: Reusing the Existing Service Descriptor

IServiceCollection is largely a wrapper around a list of ServiceDescriptor objects so we can go grab the existing registration and use that in our factory.

class Decorator : IService {
  public Decorator(
    IService concreteService,
    IOtherService1 anotherDependency) {}
}

public static void ConfigureServices(IServiceCollection services) {
  var wrappedServiceDescriptor = services.First(s => s.ServiceType == typeof(IService));

  services.Replace(ServiceDescriptor.Describe(
    typeof(IService),
    s => new Decorator(
      s.CreateInstance(wrappedServiceDescriptor),
      s.GetRequiresService<IOtherService1>()),
    wrappedServiceDescriptor.Lifetime
  ));
}

public static object CreateInstance(this IServiceProvider services, ServiceDescriptor descriptor)
{
  if (descriptor.ImplementationInstance != null)
    return descriptor.ImplementationInstance;

  if (descriptor.ImplementationFactory != null)
    return descriptor.ImplementationFactory(services);

  return ActivatorUtilities.GetServiceOrCreateInstance(services, descriptor.ImplementationType);
}

Here we use the existing service descriptor to resolve an instance that we can pass into our constructor, as well as copying the defined service lifetime. We’re using the CreateInstance helper method to create an instance of the wrapped type from the service descriptor.

  • ✅ Decorator can construct on an interface
  • ✅ No longer requires the decorated implementation to be registered agaist it’s concrete type
  • ✅ Copies service lifetime from wrapped service
  • ❌ Still forces you to manually maintain other dependencies for Decorator

Closer, but we still have the pain point of managing dependencies when Decorator changes in the future.

Approach #4: Use an Intermediate Scope

Use the dependency injection framework to instantiate the decorator from the services registered so far.

//Decorator class as above

public static void ConfigureServices(IServiceCollection services) {
  var wrappedServiceDescriptor = services.First(s => s.ServiceType == typeof(IService));

  // add the decorator as a concrete type (with the same lifetime as the wrapped service)
  services.Add(ServiceDescriptor.Describe(typeof(Decorator), typeof(Decorator), wrappedServiceDescriptor.Lifetime);

  // build a new service provider that contains the decorator
  // as a concrete type and the wrapped service as the interface
  // (as well as anything that has already been registered)
  var intermediateProvider = services.BuildServiceProvider();

  // replace the interface registration by resolving the
  // decorator type from the intermediate provider
  services.Replace(ServiceDescriptor.Describe(
    typeof(IService),
    s => intermediateProvider.GetRequiredService<Decorator>(),
    wrappedServiceDescriptor.Lifetime
  ));
}
  • ✅ Decorator can construct on an interface
  • ✅ Can register decorated implementation against interface
  • ✅ Automatically handles dependency changes
  • ❌ Can cause scope issues with other dependencies

This version is pretty good but it does have a subtle problem: the intermediate scope will only contain services that have been registered at the time this code is called. This means that if either Decorator or the wrapped service have other dependencies that are registered later then they won’t be available.

This is possibly not the worst problem in the world but it could lead to a nasty category of bug that would be very difficult to track down. Can we do better?

Going to the Source

By this point we can define our ideal solution as something like:

var existingService = services.First(s => s.ServiceType == typeof(IService));
services.Replace(ServiceDescriptor.Describe(
  typeof(IService),
  s => s.GetRequiredService<Decorator>(/* somehow pass in existingService here */),
  existingService.Lifetime)
);

i.e. we want to use the existing service registration but only while resolving the decorator. Anything else resolving IService from the container should get the decorator.

While researching this problem, the closest analogue that came to mind was the way in which HttpClientFactory injects specific HttpClient instances into resolved classes. After a few minutes digging through the source (open source FTW!) I found their implementation including a few useful utilities that can help us out here.

ActivatorUtilities & ObjectFactory

The ActivatorUtilities.CreateFactory helper method creates a factory function for a concrete type:

var objectFactory = ActivatorUtilities.CreateFactory(
  typeof(Decorator), 
  new[] { typeof(IService) });

The second parameter is an array of the types that we can explicitly provide to the created objectFactory function. In this case, we will provide an explicitly-specified instance of IService but every other constructor parameter should be sourced from a service provider.

We invoke the objectFactory by passing in a service provider as well as an array of concrete instances of the types specified above.

ServiceDescriptor wrappedDescriptor;
IServiceProvider services;
var instanceOfDecorator = objectFactory(
  services, 
  new [] { services.CreateInstance(wrappedDescriptor) });

These 2 methods together give us exactly what we need:

  • ✅ Decorator can construct on an interface
  • ✅ Wrapped implementation can be registered against the interface
  • ✅ Decorator scope is taken from wrapped service
  • ✅ Dependencies in wrapped implementation are injected automatically
  • ✅ Dependencies in decorator are injected automatically

Here’s our final implementation, converted into a generic extension method on the IServiceCollection:

public static class ServiceCollectionExtensions {

  public static void Decorate<TInterface, TDecorator>(this IServiceCollection services)
    where TInterface : class
    where TDecorator : class, TInterface
  {
    // grab the existing registration
    var wrappedDescriptor = services.FirstOrDefault(
      s => s.ServiceType == typeof(TInterface));

    // check it's valid
    if (wrappedDescriptor == null) 
      throw new InvalidOperationException($"{typeof(TInterface).Name} is not registered");

    // create the object factory for our decorator type,
    // specifying that we will supply TInterface explicitly
    var objectFactory = ActivatorUtilities.CreateFactory(
      typeof(TDecorator), 
      new[] { typeof(TInterface) });

    // replace the existing registration with one
    // that passes an instance of the existing registration
    // to the object factory for the decorator
    services.Replace(ServiceDescriptor.Describe(
      typeof(TInterface),
      s => (TInterface)objectFactory(s, new[] { s.CreateInstance(wrappedDescriptor) }),
      wrappedDescriptor.Lifetime)
    );
  }

  private static object CreateInstance(this IServiceProvider services, ServiceDescriptor descriptor)
  {
    if (descriptor.ImplementationInstance != null)
      return descriptor.ImplementationInstance;

    if (descriptor.ImplementationFactory != null)
      return descriptor.ImplementationFactory(services);

    return ActivatorUtilities.GetServiceOrCreateInstance(services, descriptor.ImplementationType);
  }
}

Our sample usage is now nice and easy. We can even stack more than one decorator with each one wrapping the previously-registered type!

public static void ConfigureServices(IServiceCollection services) {
  services.AddScoped<IService, DbService>();
  services.Decorate<IService, LoggingService>();
  services.Decorate<IService, ExceptionHandlingService>(); //etc.

  // IService resolves to:
  //  an ExceptionHandlingService
  //    wrapping a LoggingService
  //      wrapping a DbService
}

I’m not sure why this was such a complicated thing to achieve with the dependency injection framework – it is certainly easier in, for example, Autofac – but it goes to show the great advantage of open source: you can almost always find a way!

Conditional Rendering in React

Conditionally rendering content is a pretty common pattern in React components.

class MyComponent extends Component {
  render() {
    const { user } = this.props;
    return (
      <div>
        {user && <h1>{user.name}</h1>}
        {/* other content */}
      </div>
    );
  }
}

This can quickly get messy when you introduce multiple parmeters or large conditional content blocks

render() {
  const { user, profile, otherData } = this.props;
  const shouldDisplayProfile = user && profile && otherData;
  return (
    <div>
      {shouldDisplayProfile &&
        <div>





        </div>
      }
      {/* other content */}
    </div>
  );
}

And don’t even mention ternary operators. Nothing better than scrolling through a component and finding : null} with no context 👀

Wrapping Dependent Content

In React, our unit of reuse is usually a component so can we move this behaviour into a component?

const example = (
  <OnlyIf all={{ user, profile, otherData }}>
    only render this content if all of user, profile & otherData are defined
  </OnlyIf>
);

It turns out that this is actually a pretty simple component:

  1. determine if the all prop values are truthy
  2. only render the children if they are
interface OnlyIfProps<T> {
  all: T;
}

class OnlyIf<T> extends PureComponent<OnlyIfProps<T>> {
  render() {
    const { all, children } = this.props;

    let allValuesSpecified = true;
    Object.keys(all).forEach(
      key => (allValuesSpecified = allValuesSpecified && !!all[key])
    );

    return allValuesSpecified ? children : null;
  }
}

Lazy Rendering Content

The “ component above may be useful but there is an important scenario that is not covered: children attempting to use undefined values.

const example = (
  <OnlyIf all={{ user }}>
    <h1>{user.name}</h1> {/* <-- this will throw if user is undefined */}
  </OnlyIf>
);

In this case we shouldn’t even attempt to render the children if user is undefined. We cannot prevent it when we use the structure above but if we switch to a render props pattern then we can control when children are rendererd:

const example = (
  <OnlyIf all={{ user }}>{values => <h1>{values.user.name}</h1>}</OnlyIf>
);

We can update our component to support both scenarios by…

  1. accepting either ReactNode (the default) or (values: T) =&gt; ReactNode as our children
  2. identifying the function in render and invoking it
interface OnlyIfProps<T> {
  all: T;
  children: ReactNode | ((values: T) => ReactNode);
}

class OnlyIf<T> extends PureComponent<OnlyIfProps<T>> {
  render() {
    const { all, children } = this.props;

    let allValuesSpecified = true;
    Object.keys(all).forEach(
      key => (allValuesSpecified = allValuesSpecified && !!all[key])
    );

    if (!allValuesSpecified) return null;

    return typeof children === 'function' ? children(all) : children;
  }
}

Now we can accept either a render function or a component as the situation demands!

Is this a good idea?

So we absolutely can create “ but is it useful?

On the negative side, it is an unfamiliar component that may have unexpected effects for new developers.

On the other hand, it’s fairly self explanatory and is an improvement in general readability in my opinion.

Overall I think it’s a nice addition. It certainly beats the hell out of a 20 line ternary expression!

Higher-Order Components with React & TypeScript

Higher-order components are a great way of reusing common functionality in your react app.

TypeScript is a great way of making sure your react app can grow without you losing your mind.

So how can we use the two together?

Higher-Order Components

A higher-order component (HoC) is a function that accepts a component as an argument and returns a new component that has been enhanced in some way.

const EnhancedComponent = myHigherOrderComponent(WrappedComponent);

The enhanced component can add behaviour, manage state or in any other way modify WrappedComponent.

Injecting Props

A common pattern is for a higher-order component to provide some props to the wrapped component, moving the management of those props out of WrappedComponent and allowing it to focus on other concerns.

For example, connect(...)(WrappedComponent) in react-redux provides props to both expose redux state and to dispatch actions. withRouter(WrappedComponent) in react-router similarly injects routing-related props into WrappedComponent from the current route.

Getting the prop types right when injecting props can be a bit fiddly. We want:

  1. WrappedComponent to have new props injected automatically
  2. Injected props not to be required on the created EnhancedComponent
  3. Any other props on WrappedComponent to be forwarded from EnhancedComponent
  4. TypeScript to infer all of the above with no manual specification for the user

For example, let’s say we have a HoC that will manage the isExpanded state of an expander component. It will provide the following props to WrappedComponent

interface ExpanderProps {
  isExpanded: boolean;
  toggleExpanded(): void;
}

Our wrapped component will need to accept these props but it might define some others as well. Let’s say it has a title that needs to be specified and an optional className:

interface WrappedComponentProps {
  isExpanded: boolean;
  toggleExpanded(): void;
  title: string;
  className?: string;
}

note that you could (and should!) define this as WrappedComponentProps extends ExpanderProps... and avoid duplicating the prop definitions. I’ve left this as it is here for clarity

In this case we want both title and className to be available on EnhancedComponent:

const EnhancedComponent = withExpander(WrappedComponent);

const usage = (
  <EnhancedComponent
    title="The title"
    className="class-name">
    ...
  </EnhancedComponent>
);

The Wrapped Component

At this stage we have already defined the provided props as an interface and we have an example of what the wrapped component might look like. Let’s flesh that out a bit (and give it a more appropriate name):

interface ExpanderComponentProps extends ExpanderProps {
  title: string;
}

class ExpanderComponent extends PureComponent<ExpanderComponentProps> {
  render() {
    const { isExpanded, toggleExpanded, title, children } = this.props;

    return (
      <>
        <button onClick={toggleExpanded}>{title}</button>
        {isExpanded && children}
      </>
    );
  }
}

Fairly simple: render a button containing title that toggles the expanded state. If isExpanded=true then also render the children.

Create the Enhancer

Now we want to create the enhancer function that we can use to inject isExpanded and toggleExpanded. Our first requirement is that it accepts an argument of WrappedComponent where WrappedComponent accepts the props we want to inject. That function signature might look something like this:

function withExpander(WrappedComponent: ComponentType<ExpanderProps>) {
  //...
}

ComponentType is a react type that allows you to pass in either a component class or a stateless functional component that has props of T

The next requirement is that it returns a component that doesn’t require the ExpanderProps to be specified, which means that we need to provide them from the enhanced component. In this case we’re going to get those values from the state on the component but that’s not a requirement – they can come from anywhere.

Once we have the values we need we can pass them to WrappedComponent in the render method:

function withExpander(WrappedComponent: ComponentType<ExpanderProps>) {
  return class WithExpander extends PureComponent<{}, { isExpanded: boolean }> {
    render() {
      return <WrappedComponent
        {...this.state}
        toggleExpanded={this.toggleExpanded}
        />
    }

    private toggleExpanded = () => this.setState(state => ({ isExpanded: !state.isExpanded }));
  }
}

All right, nice and easy! Except… build failure!

const EnhancedComponent = withExpander(ExpanderComponent);
// Error!

Our ExpanderComponent requires a title prop; when we use it (as WrappedComponent) in withExpander we don’t specify the title!

We could make withExpander aware of the title prop but that’s not very useful for the future: there will likely be other props that need to be passed through and we don’t want to keep adding them to our HoC.

This brings us on to Requirement 3 above: any other props from the wrapped component should be forwarded from the enhanced component. In this case, we really want to have the title prop be exposed on EnhancedComponent.

The first step in getting to that point is to allow the WrappedComponent parameter of our HoC to accept props that aren’t on ExpanderProps. In fact, we need our wrapped component to accept props of both ExpanderProps and whatever else it wants.

We can introduce a generic type parameter to the HoC function to represent that combined props object:

function withExpander<TWrappedComponentProps extends ExpanderProps>(
  WrappedComponent: ComponentType<TWrappedComponentProps> ) {
  //...
}

That solves our build failure: withExpander will now accept any component as long as it has the two isExpanded and toggleExpanded props.

Sadly we’re not quite done yet though; try to use the enhanced component and you will see our next problem:

const EnhancedComponent = withExpander(ExpanderComponent);

const usage = <EnhancedComponent title="Some title" />;
// Error!

Another build failure, this time telling us that title does not exist on the enhanced component. We’ve managed to write our HoC so that it allows extra props but all it does is ignore them!

What we really want here is to create a new Props type that we can assign to our created component. TypeScript 2.8 includes 2 built-in types that are going to help us out:

  • Pick<T, U> that takes the props from T specified in U. e.g. Pick<ExpanderProps, ‘isExpanded’> creates a type with only the isExpanded property
  • Exclude<T, U> that takes everything from T except U. e.g. Exclude<‘one’ | ‘two’ | ‘three’, ‘two’>* creates a type 'one' | 'three'

By combining these with keyof we can build up the “all props that are on the inner component but excluding the ones we’re providing” type. We might want a better name though…

function withExpander<TWrappedComponentProps extends ExpanderProps>(WrappedComponent: ComponentType<TWrappedComponentProps>) {
  type WrappedComponentPropsExceptProvided = Exclude<keyof TWrappedComponentProps, keyof ExpanderProps>;
  // => 'title' | 'className'
  type ForwardedProps = Pick<TWrappedComponentProps, WrappedComponentPropsExceptProvided>;
  // => { title: string; className?: string }

  //...
}

Now that we know what our forwarded props should look like we can specify those on the component.

return class WithExpander extends PureComponent<
  ForwardedProps,
  { isExpanded: boolean }
> {
  render() {
    return (
      <WrappedComponent
        {...this.props}
        {...this.state}
        toggleExpanded={this.toggleExpanded}
      />
    );
  }

  //...
};

the additional spread of this.props onto WrappedComponent copies the externally-specified props onto the wrapped component

Now we can use our enhanced component as intended.

const EnhancedComponent = withExpander(ExpanderComponent);

const usage = (
  <EnhancedComponent title="title">
    <div>...</div>
  </EnhancedComponent>
);

As a bonus, TypeScript gives us Requirement 4 for free! Type inference means that we don’t have to specify any types explicitly in our usage of this HoC but we still have full type safety. Try removing title or adding an unknown property and your IDE will light up with compilation errors – thanks TypeScript! ✨

Post-Logout Redirect with ASP.NET Core and ADFS 2016

Redirect after logout

When a user logs out from your app you have the option to log them out of the provider as well by redirecting the browser to the logout endpoint. By default this means that the user will end up sat on your providers “You have signed out” page – not brilliant.

You can, however, tell your provider to redirect back to your app once they’re done with logout by specifying a post_logout_redirect_uri.

For ASP.NET Core Identity you can specify this redirection as a parameter on the SignOutResult.

[Route("auth")]
public class AuthController
{
  [HttpPost("logout")]
  public IActionResult Logout() => new SignOutResult(
    OpenIdConnectDefaults.AuthenticationScheme,
    new AuthenticationProperties { RedirectUri = Url.Action(nameof(LogoutSuccess))});

  [HttpGet("logoutSuccess")]
  public IActionResult LogoutSuccess() => View();
}

Useless ADFS error messages

For ADFS 2016 you need to do a little bit more than just set the redirect URL. On first inspection you can see that the above will set the parameter in the ADFS URL but ADFS will silently ignore it and your user will sit forever on the ADFS sign-out page.

Digging into the event logs you will find the following error message:

The specified redirect URL did not match any of the OAuth client’s redirect URIs. The logout was successful but the client will not be redirected

If you’re unlucky, this wonderfully-misleading error message can take you down a rabbit hole of further configuration. It’s a shame, then, that no-one thought to expose something a little more accurate:

That redirect looks good but you need to specify id_token_hint or we’ll ignore you

Thanks ADFS!

Sending ID Token Hint

To be fair to ADFS, sending an id_token_hint is recommended by the spec. This parameter needs to be set to the id_token that was sent to your app when the user first logged in; provide this value and ADFS will happily redirect back to your app.

The only problem here is that you probably don’t still have that id_token. ASP.NET Core Identity uses the identity information to create an auth cookie and then (by default) discards it.

Happily, the OpenIdConnectOptions exposes a SaveTokens property to persist the received token to the auth cookie. Even better: the OIDC logout mechanism will automatically pick this up once enabled so you should be good to go as soon as you set the flag:

public class Startup {
  public void ConfigureServices(IServiceCollection services)
  {
    services.AddAuthentication()
      .AddOpenIdConnect(options => {
        options.SaveTokens = true;
        //...set other options
      });

    //...other service config
  }
}

This does have one important downside though: you’re now storing much more information in your auth cookie and that adds extra data to every client request, maybe even doubling the cookie size.

Whether or not this is a problem for your app is another decision – at least your logout redirect works now!