Como vimos en el post introductorio, cuando intentamos navegar hacia una página que no esta activa debido a un Feature Flag desactivado recibimos un mensaje de error 404 - Not Found o Página no encontrada.

En algunos escenarios ese error puede ser suficiente, pero en determinadas ocasiones, redireccionar al usuario a otra pagina o devolver algún otro código de error puede resultar una mejor opción.

Requerimiento

Nuestro sitio web tiene una vista con todos los productos que tienen un descuento especial por Navidad. Utilizamos Feature Flags condicionales para garantizar que esta funcionalidad este activa solo los días 24 y 25 de Diciembre.

Cuando un usuario accede a esta lista especial de descuentos fuera del periodo navideño, queremos redireccionar al usuario a otra vista para informarle que los descuentos ya no se encuentran disponibles e invitarlo a revisar otros posibles descuentos.

IDisabledFeaturesHandler

Para poder manejar en forma personalizada cómo respondemos ante una funcionalidad inactiva, tenemos la opción de implementar al interface IDisabledFeaturesHandler:

public interface IDisabledFeaturesHandler
{
    Task HandleDisabledFeatures(
        IEnumerable<string> features,
        ActionExecutingContext context);
}

Como podemos observar, la interfaz tiene solo un método con la lista de Feature Flags que se requirieron y el contexto de MVC actual. Veamos en detalle que significa cada uno de esos parámetros.

IEnumerable<string> features

El primer parámetro contiene la lista de todos los Feature Flags que fueron requeridos para poder acceder a la funcionalidad en cuestión. Alguno o algunos de ellos se encuentran inactivos y dispararon el manejador.

Recordemos que cuando una funcioalidad puede dependender de más de un Feature Flag, y además podemos requerir que todos los Feature Flags esten activos o al menos uno. En los siguiente ejemplo lo vemos en forma más detallada:

public class MyController : Controller
{
    // Cualquiera de los features es suficiente
    [FeatureGate(
        RequirementType.Any, 
        "FeatureFlag1", 
        "FeatureFlag2")]
    public IActionResult Funcionalidad1() => 
        View();

    // Ambos features deben estar activos
    [FeatureGate(
        RequirementType.All, 
        "FeatureFlag1", 
        "FeatureFlag2")]
    public IActionResult Funcionalidad2() => 
        View();
}

ActionExecutingContext context

Este parámetro corresponde al contexto de ejecución de la acción dentro de MVC (el mismo que tenemos disponibles en los Action Filters!!!) y nos brinda por un lado información sobre el controlador y acción que se intentaron ejecutar, por el otro lado nos permite manejar la respuesta que enviaremos al cliente.

Manos a la obra

Para completar nuestro requerimiento vamos a generar una nueva clase, la cual llamaremos DisabledFeaturesHandler, e implementaremos la interfaz IDisabledFeaturesHandler.

En el método HandleDisabledFeatures redireccionaremos al usuario a una vista llamada OtherDiscounts.cshtml donde le notificaremos que los descuentos ya no están disponibles.

public class DisabledFeatureHandler : IDisabledFeaturesHandler
{
    public Task HandleDisabledFeatures(
        IEnumerable<string> features,
        ActionExecutingContext context)
    {
        var viewResult = new ViewResult
        {
            ViewName = "Views/Home/OtherDiscounts.cshtml"
        };

        context.Result = viewResult;

        return Task.CompletedTask;
    }
}

Por último, tenemos que incluir este manejador como parte de los servicios responsables del manejo de Features Flags. Esto lo haremos en ConfigureServices de la clase Startup:

public class Startup
{
    public void ConfigureServices(
        IServiceCollection services)
    {
        // ...
        services.AddFeatureManagement()
            .UseDisabledFeaturesHandler(
                new DisabledFeaturesHandler());
    }

    public void Configure(
        IApplicationBuilder app)
    {
        // ...
    }
}

A partir de este momento, cada vez que el usuario se dirija a la vista de descuentos navideños fuera del periodo correspondiente, será automáticamente redirigido a una vista particular en lugar de recibir un error 404 - NotFound:

Manejador de Feature Flags inactivos.

Conclusión

En este post vimos como con muy poquito codigo podemos manejar de forma elegante y simple como reaccionar en forma particular a alguna funcionalidad que se encuentra deshabilitada y tenemos la necesidad de responder de una manera diferente.

Todavía nos queda mucho por descubrir sobre manejo de sesión, implementación de filtros personalizados, middlewares y much más.