Aggiunta di flag di funzionalità in ASP.NET

Aggiunta di flag di funzionalità in ASP.NET

In ASP.NET, puoi aggiungere i tuoi flag di funzionalità usando la funzionalità di gestione delle funzionalità.

In questo articolo, mostrerò come configurare e utilizzare la gestione delle funzionalità in ASP.NET e come utilizzarla per eseguire il gate di funzionalità di un endpoint utilizzando il proprio flag di funzionalità.

Configura la gestione delle funzionalità

È necessario eseguire alcuni passaggi di configurazione per poter utilizzare la gestione delle funzionalità. È necessario aggiungere il pacchetto nuget di gestione delle funzionalità, aggiungere i flag delle funzionalità a appsettings.json e abilitare la gestione delle funzionalità in Startup.ConfigureServices. Questi passaggi sono mostrati di seguito.

Installa il pacchetto nuget di gestione delle funzionalità

Installare il pacchetto nuget Microsoft.FeatureManagement.AspNetCore. Nota:sta usando (Visualizza> Altre finestre> Console di gestione pacchetti) .

Install-Package Microsoft.FeatureManagement.AspNetCore
Code language: PowerShell (powershell)

Aggiungi flag di funzionalità a appsettings.json

Per impostazione predefinita, ASP.NET legge i flag di funzionalità da una proprietà in appsettings.json denominata FeatureManagement . Quindi aggiungi questa proprietà e tutti i tuoi flag di funzionalità ad appsettings.json, in questo modo:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "FeatureManagement": {
    "Movies": true,
    "Shows":  true
  }
}

Code language: JSON / JSON with Comments (json)

In questo esempio, ho due funzionalità:Film e Programmi.

Quando controlli se una funzione è abilitata, devi passare il nome della funzione. Invece di passare in stringhe letterali, puoi inserire i nomi delle funzioni in un'enumerazione, come questa:

public enum Features
{
	Movies,
	Shows
}
Code language: C# (cs)

Nota:puoi anche utilizzare le costanti per i nomi delle funzioni, se è quello che preferisci.

Attiva la gestione delle funzionalità

In Startup.ConfigureServices, aggiungi services.AddFeatureManagement(), in questo modo:

using Microsoft.FeatureManagement;
    
public class Startup
{
	public void ConfigureServices(IServiceCollection services)
	{
		services.AddFeatureManagement();

		//other things in ConfigureServices
	}

//other things in Startup
Code language: C# (cs)

Una volta attivata la gestione delle funzionalità, il framework farà un sacco di lavoro pesante per te. Leggerà i flag delle funzionalità da appsettings.json e potrai iniziare immediatamente a utilizzarli nel servizio.

Funzionalità gating controller ed endpoint

Dopo aver configurato la gestione delle funzionalità, è possibile utilizzare i flag delle funzionalità in molti modi.

Un uso comune dei flag di funzionalità è il gate delle funzionalità dei controller e degli endpoint. Ciò significa che quando la tua funzione è disattivata, le richieste restituiranno una risposta 404 (non trovata). Questo è un modo conveniente per disabilitare gli endpoint.

Nota:puoi modificare il comportamento di ciò che restituisce quando una funzione è disabilitata. Lo mostrerò anche qui sotto.

Feature Gate un controller

Per eseguire il gate di funzionalità di un controller, utilizzare l'attributo FeatureGate sul controller e specificare la funzionalità, in questo modo:

using Microsoft.FeatureManagement.Mvc;

[FeatureGate(Features.Movies)]
[ApiController]
[Route("[controller]")]
public class MovieController : ControllerBase
{

	[HttpGet]
	public IEnumerable<Movie> Get()
	{
		return new List<Movie>()
		{ 
			new Movie()
			{
				Name = "Office Space",
				Description = "A relatable comedy about a programmer who hates works",
				RuntimeMinutes = 89,
				ReleaseYear = 1999
			}
		};
	}
}
Code language: C# (cs)

Prova a inviare una richiesta GET a questo controller con il flag di funzionalità abilitato. Quando è abilitato, riceverai un codice di risposta 200 e il JSON restituito dall'endpoint, come previsto.

Ora guarda cosa succede quando disabiliti il ​​flag della funzione. Imposta il flag della funzionalità su false in appsettings.json:

{
  "FeatureManagement": {
    "Movies": false,
    "Shows": true
  }
}
Code language: JSON / JSON with Comments (json)

Quando invii una richiesta GET con il flag di funzionalità disabilitato, otterrai il codice di stato HTTP 404 (non trovato).

Feature gate a un singolo endpoint

È possibile caratterizzare i singoli endpoint del gate. Questo è utile se non si desidera utilizzare il gate per l'intero controller. Funziona come la funzionalità di gating di un controller:quando la funzionalità è disabilitata, le richieste all'endpoint restituiranno un 404 (non trovato).

Ecco come eseguire il gate delle funzionalità dell'endpoint:

using Microsoft.FeatureManagement.Mvc;

[ApiController]
[Route("[controller]")]
public class MovieController : ControllerBase
{
	[FeatureGate(Features.Movies)]
	[HttpGet]
	public IEnumerable<Movie> Get()
	{
		return new List<Movie>()
		{
			new Movie()
			{
				Name = "Office Space",
				Description = "A relatable comedy about a programmer who hates works",
				RuntimeMinutes = 89,
				ReleaseYear = 1999
			}
		};
	}
}
Code language: C# (cs)

Quando hai abilitato il flag della funzionalità, le richieste passeranno all'endpoint e torneranno come previsto.

Quando il flag di funzionalità è disabilitato, l'endpoint restituirà un 404 (non trovato).

Modifica ciò che viene restituito quando una funzione è disabilitata

Il comportamento predefinito per le funzioni disabilitate è ragionevole. Restituisce una risposta 404 (non trovato).

Ma cosa succede se si desidera modificare quel comportamento predefinito? Ad esempio, supponiamo che tu voglia restituire un codice di stato 500 e restituire un messaggio di risposta intuitivo che indichi esattamente quali funzionalità disabilitate non consentono l'azione.

Innanzitutto, aggiungi una classe che implementi l'interfaccia IDisabledFeaturesHandler, come questa:

using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.FeatureManagement.Mvc;

public class DisabledFeatureHandler : IDisabledFeaturesHandler
{
	public Task HandleDisabledFeatures(IEnumerable<string> features, ActionExecutingContext context)
	{
		context.Result = new ObjectResult($"Action disallowed. Feature(s) are disabled: {string.Join(", ", features)}") 
		{ 
			StatusCode = 500 
		};
		return Task.CompletedTask;
	}
}
Code language: C# (cs)

Quindi in Startup.ConfigureServices, chiama UseDisableFeaturesHandler() in questo modo:

using Microsoft.FeatureManagement;
public class Startup
{

	public void ConfigureServices(IServiceCollection services)
	{
		services.AddFeatureManagement()
			.UseDisabledFeaturesHandler(new DisabledFeatureHandler());

		//Other things in ConfigureServices
	}
	
	//other things in Startup

Code language: C# (cs)

Per vedere che funziona, disattiva una funzione in appsettings.json:

{
  "FeatureManagement": {
    "Movies": false,
    "Shows": true
  }
}
Code language: JSON / JSON with Comments (json)

Quando provi a raggiungere l'endpoint con la funzione disabilitata, tornerai indietro:

Status Code: 500
Body: "Feature(s) are disabled: Movies"Code language: plaintext (plaintext)

Passare il FeatureManager a un controller

La gestione delle funzionalità in ASP.NET è molto flessibile. Puoi passare FeatureManager ovunque nel tuo codice e verificare se un flag di funzionalità è abilitato.

Supponiamo che tu abbia un endpoint a cui desideri includere il gate, ma non desideri utilizzare l'attributo FeatureGate. E quando la funzione è disabilitata, vuoi restituire una risposta di errore molto specifica.

Innanzitutto, la dipendenza inietta IFeatureManager nel controller aggiungendolo come parametro del costruttore. Quindi usa FeatureManager.IsEnabledAsync() e specifica il nome della tua funzione, in questo modo:

using Microsoft.FeatureManagement;

[ApiController]
[Route("[controller]")]
public class ShowController : ControllerBase
{
	private readonly IFeatureManager FeatureManager;
	public ShowController(IFeatureManager featureManager)
	{
		FeatureManager = featureManager;
	}

	[HttpGet]
	public async Task<IActionResult> Get()
	{
		if (!await FeatureManager.IsEnabledAsync(nameof(Features.Shows)))
			return Problem($"{nameof(Features.Shows)} feature is not enabled");

		return Ok(new List<Show>()
		{
			new Show()
			{
				Name = "The Office",
				Description = "A relatable comedy about what office workers do to survive the boredom of pointless work",
				NumberOfEpisodes = 201,
				NumberOfSeasons = 9,
				FirstYear = 2005,
				LastYear = 2013
			}
		});
	}
}
Code language: C# (cs)

Disabilita la funzione in appsettings.json:

{
  "FeatureManagement": {
    "Movies": false,
    "Shows": false
  }
}
Code language: JSON / JSON with Comments (json)

Ora invia la richiesta e riceverai un codice di errore 500 con il messaggio di risposta specificato dal codice dell'endpoint:

{
    "type": "https://tools.ietf.org/html/rfc7231#section-6.6.1",
    "title": "An error occured while processing your request.",
    "status": 500,
    "detail": "Shows feature is not enabled",
    "traceId": "|2b03078e-4ca4f4728d2f1a37."
}
Code language: JSON / JSON with Comments (json)