Feature Flags for ASP.Net Core Applications: Handling Action Disabled by Feature Flags

Feature Flags for ASP.Net Core Applications: Handling Action Disabled by Feature Flags

Feature Flags for ASP.Net Core Applications Series

Even if you use a FeatureGate filter attribute on a controller action, you can still navigate to the controller actions. Or if you enabled a feature for a certain time and then disabled it until you make the final changes, a user might have bookmarked the URLs and try to navigate to those features. So, it’s a good practice to handle those scenarios in a more user-friendly way.

Default Behavior

By default, when a feature flag is disabled and if someone navigates to the disabled feature it will throw a 404 Not Found result to the browser.

404 Page Shown by Default

Changing Default Behavior

To change the default way of handling the navigation to a disabled feature you need to create and register an implementation for the IDisabledFeaturesHandler interface. The following implementation will redirect the users to a dedicated page for notifying about disabled features.

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.FeatureManagement.Mvc;
using MusicStore.Web.Models;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Mvc.ModelBinding;

namespace MusicStore.Web.FeatureManagement
{
  public class MusicStoreDisabledFeaturesHandler : IDisabledFeaturesHandler
  {
    public Task HandleDisabledFeatures(IEnumerable<string> features, ActionExecutingContext context)
    {
      var vm = new DisabledFeatureViewModel
      {
        FeatureName = string.Join(", ", features),
        GoLiveDate = DateTimeOffset.UtcNow.AddDays(30)
      };

      var viewResult = new ViewResult
      {
        ViewName = "Views/Error/DisabledFeature.cshtml",
        ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())
        {
          Model = vm
        }
      };

      context.Result = viewResult;
      return Task.CompletedTask;
    }
  }
}

Here I am redirecting the user to a MVC view that takes in a DisabledFeatureViewModel class with the name of the feature that is disabled and a go live date.

using System;

namespace MusicStore.Web.Models
{
  public class DisabledFeatureViewModel
  {
    public string FeatureName { get; set; }
    public DateTimeOffset GoLiveDate { get; set; }
  }
}

Then the Razor view will display the information passed in this View model.

@model DisabledFeatureViewModel
@{
  ViewData["Title"] = "Feature Disabled";
}
<div class="text-center">
  <div class="row">
    <img class="col-md-8 offset-2 img-fluid" src="~/img/feature_disabled.png" alt="feature disavled" />
  </div>
  <div class="text-center">
    <p class="lead "><b>@Model.FeatureName</b> feature you are trying to access is disabled. Planned date for @Model.FeatureName feature to come online is on <b>@Model.GoLiveDate.ToLocalTime()</b>.</p>
    <p class="lead text-center">For additional information contact us at <a href="#">[email protected]</a></p>
  </div>
</div>

To make everything work, we need to register the IDisabledFeaturesHandler implementation in the ConfigureServices() in the Startup.cs. This is done using the UseDisabledFeatureHandler extension method on IFeatureManagementBuilder.

namespace MusicStore.Web
{
  public class Startup
  {
    ...

    public void ConfigureServices(IServiceCollection services)
    {
      ...

      services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

      // Configure Feature Management
      services
        .AddFeatureManagement()
        .AddFeatureFilter<BrowserFilter>()
        .UseDisabledFeaturesHandler(new MusicStoreDisabledFeaturesHandler());

      ...
    }
  }
}

Now when the user tries to access a disabled feature they will be redirected to this new view. In our Music Store application, the Promotions feature is disabled and when trying to access the page this is the result.

2 accessing disabled feature custom implementation

Summary

By providing a custom implementation for IDisabledFeaturesHandler you can provide a better user experience when trying to navigate to a disabled feature.

You Might Also Like
Comments