wake-up-neo.com

Wie bekomme ich IOptions in der ConfigureServices-Methode?

Ich habe eine asp.net-Kernanwendung. Ich möchte IOptions pattern verwenden, um Werte aus appsettings.json einzufügen. Ich habe also eine Klasse SecurityHeaderOptions und auch eine Zielklasse SecurityHeadersBuilder, deren Konstruktor IOptions<SecurityHeaderOptions> als Parameter verwendet.

Ich weiß, dass .net Core die Instanz von SecurityHeadersBuilder implizit erstellen kann, indem IOptions<SecurityHeaderOptions> nach der Registrierung beider Container in Container eingefügt wird.

Ich möchte jedoch die Instanz von SecurityHeadersBuilder explizit erstellen, eine ihrer Methoden aufrufen und dann die Instanz beim Container registrieren.

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;
    }
 }

ConfigureServices-Methode

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

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

   }

Fragen
1> Wenn ich Optionen explizit an Konstruktor übergeben möchte, muss ich SecurityHeaderOptions mit dem Container mithilfe der service.Configure-Methode registrieren? 

2> Configuration.GetSection("SecurityHeaderOptions") kann keine Instanz von IOptions<SecurityHeaderOptions> zurückgeben, stattdessen IConfigurationSection.

3> Wie kann ich auf jeden Fall SecurityHeaderOptions abrufen und in den Konstruktor von SecurityHeadersBuilder übergeben?

18
LP13

Mit .NET Core 2 und nicht mit einem Anbieter in ConfigureServices (oder mit dem Gedanken, es hinzuzufügen) habe ich mich für Folgendes entschieden (Beispiel: OP-Code)

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

        ...
    }
11
Quinton Smith

So registriere ich Optionen und füge in SecurityHeadersBuilder ein

    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

In Bezug auf Ihre Fragen:

1. Ja, Sie müssen die Optionen registrieren, aber ich glaube, dass Sie es falsch machen (zumindest durch Ihr Beispiel). Sie sollten sich wie folgt registrieren:

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

2. Ich glaube, dass die korrekte Registrierung, auf die ich mich bezogen habe, das zurückgibt, was Sie erwarten.

3. Es reicht aus, es zu registrieren und im Konstruktor SecurityHeaderBuilder abzulegen. Sie müssen (und der Standardcontainer von .NET Core IOC nicht erlaubt) die Konstruktorparameter bei der Registrierung nicht übergeben. Dafür müssten Sie andere IOCs wie Autofac verwenden.

Sie müssen jedoch SecurityHeadersBuilder registrieren, um sie in anderen Klassen verwenden zu können. Verwenden Sie dazu einfach eine Schnittstelle.

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;
    }
 }

Dann registrieren Sie es einfach in startup.cs

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