web-dev-qa-db-fra.com

Comment obtenir IOptions dans la méthode ConfigureServices?

J'ai asp.net application de base. Je souhaite utiliser le modèle IOptions pour injecter les valeurs de appsettings.json. J'ai donc une classe SecurityHeaderOptions et une classe cible SecurityHeadersBuilder dont le constructeur prend IOptions<SecurityHeaderOptions> en tant que paramètre.

Je sais que .net core peut implicitement créer une instance de SecurityHeadersBuilder en injectant IOptions<SecurityHeaderOptions> après avoir enregistré les deux avec le conteneur.

Cependant, je veux explicitement créer une instance de SecurityHeadersBuilder, appeler l'une de ses méthodes et ensuite enregistrer l'instance avec le conteneur.

public sealed class SecurityHeaderOptions
{
    public string FrameOption { get; set; }    
    public string XssProtection { get; set; }
}


public class SecurityHeadersBuilder
{
    private readonly SecurityHeaderOptions _options = null;

    public SecurityHeadersBuilder(IOptions<SecurityHeaderOptions> options)
    {
        _options = options.Value;    
    }

    public SecurityHeadersBuilder AddDefaultPolicy()
    {
        AddFrameOptions();
        AddConetntSecurityPolicy();
        return this;
    }
 }

Méthode ConfigureServices

   public void ConfigureServices(IServiceCollection services)
   {        
     services.Configure<SecurityHeaderOptions>(Configuration.GetSection("SecurityHeaderOptions"));

     services.AddScoped<SecurityHeadersBuilder>(provider => 
               new SecurityHeadersBuilder(?????).AddDefaultPolicy())

   }

Des questions
1> Si je passe explicitement des options au constructeur, dois-je enregistrer SecurityHeaderOptions avec le conteneur en utilisant la méthode service.Configure

2> Configuration.GetSection("SecurityHeaderOptions") ne peut pas renvoyer l'instance de IOptions<SecurityHeaderOptions>, mais renvoie IConfigurationSection?

3> Quoi qu’il en soit, comment puis-je récupérer et passer SecurityHeaderOptions dans le constructeur de SecurityHeadersBuilder?

18
LP13

En utilisant .NET Core 2 et n'ayant pas de fournisseur disponible (ou souhaitant l'ajouter) dans ConfigureServices, j'ai opté pour quelque chose comme ceci (en utilisant le code OP comme exemple):

    public void ConfigureServices(IServiceCollection services)
    {
        // secOpts available for use in ConfigureServices
        var secOpts = Configuration
        .GetSection("SecurityHeaderOptions")
        .Get<SecurityHeaderOptions>();

        ...
    }
11
Quinton Smith

C’est ainsi que j’enregistre des options et que j’injecte dans SecurityHeadersBuilder

    public void ConfigureServices(IServiceCollection services)
    {

        services.Configure<SecurityHeaderOptions>(Configuration.GetSection("SecurityHeaderOptions"));            
        services.AddScoped<SecurityHeadersBuilder>(provider =>
        {
            var option = provider.GetService<IOptions<SecurityHeaderOptions>>();
            return new SecurityHeadersBuilder(option)
            .AddDefaultPolicy();
        });
    }
3
LP13

Concernant vos questions:

1. Oui, vous devez enregistrer les options, mais je crois que vous le faites de la mauvaise façon (du moins selon votre exemple). Vous devriez vous enregistrer comme ceci:

services.Configure<SecurityHeaderOptions>(options => Configuration.GetSection("SecurityHeaderOptions").Bind(options));

2. Je crois que l'enregistrement correct auquel je fais référence ci-dessus renvoie ce que vous attendez.

3. Il suffit de l'enregistrer et de le placer sur le constructeur SecurityHeaderBuilder. Vous n'avez pas besoin (le conteneur par défaut .NET Core IOC ne le permet pas non plus) de passer des paramètres de constructeur lors de son enregistrement. Pour cela, vous devrez utiliser d'autres IOC, tels qu'Autofac.

Mais vous devez vous inscrire SecurityHeadersBuilder pour pouvoir l’utiliser dans d’autres classes ..__ Utilisez simplement une interface pour cela.

public interface ISecurityHeadersBuilder
{
    SecurityHeadersBuilder AddDefaultPolicy;    
}
public class SecurityHeadersBuilder : ISecurityHeadersBuilder
{
    private readonly SecurityHeaderOptions _options = null;

    public SecurityHeadersBuilder(IOptions<SecurityHeaderOptions> options)
    {
        _options = options.Value;    
    }

    public SecurityHeadersBuilder AddDefaultPolicy()
    {
        AddFrameOptions();
        AddContentSecurityPolicy();
        return this;
    }
 }

Ensuite, enregistrez-le simplement dans startup.cs comme ceci

services.AddScoped<ISecurityHeadersBuilder, SecurityHeadersBuilder>();
1
João Pereira