it-swarm.com.de

appsettings.json in ASP.net Core 2.0 Preview-Konfiguration GetSection null

Ich habe versucht, GetSection aus der injizierten Konfiguration im Startup.cs..__ aufzurufen. Der Wert war null, während indexer einen konkreten Abschnittswert non-null-Wert zurückgibt. Es scheint mir ein Fehler hinter der GetSection-Methode zu sein, oder ich bin falsch damit?

appsettings.json:

{"MyConfig": { "ConfigA": "valueA", "ConfigB": "valueB"}}

Program.cs:

    public static void Main(string[] args)
    {
        var Host = BuildWebHost(args);
        Host.Run();
    }

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build();

Startup.cs:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        var mySection = this.Configuration.GetSection("MyConfig");

        var myVal = this.Configuration["MyConfig:ConfigA"];
14
Mojmir Rychly

Ich habe zuerst geprüft, ob es Änderungen zwischen 1.1.1 und 2.x von JsonConfigurationProvider.cs gab, dem internen Code, der schließlich abrufbare Werte aus Ihrer JSON-Datei erstellt. Es gab keine Änderungen an diesem oder einem der anderen Codes, die letztendlich von Ihrer this.Configuration.GetSection("MyConfig"); aufgerufen werden.

Das Abrufen von Werten funktioniert folgendermaßen: Die Variable Configuration wird in jedem Konfigurationsanbieter in MyConfig in umgekehrter Reihenfolge nach der im Code definierten Reihenfolge suchen, bis ein Wert gefunden wird. In Ihrem Beispiel werden Provider (Json, Umgebungsvariablen, Befehlszeilenargumente) in Webhost.CreateDefaultBuilder()(hier) } bereitgestellt.

Beim Betrachten des Codes für JsonConfigurationFileParser.cs wird ein Dictionary<string, string> für Schlüssel und Werte erstellt, , jedoch nur für Grundwerte. Das heißt, es wird kein Schlüssel für MyConfig gespeichert (auf dieser Ebene ist es ein Objekt), aber es gibt einen Schlüssel für MyConfig:ConfigA und die Array-Werte würden wie MyConfig:ConfigA:0, MyConfig:ConfigA:1 usw. aussehen.

Schließlich werden Sie feststellen, dass Configuration.GetSection("MyConfig")liefert immer eine neu erstellteConfigurationSection, dh never null, und im schlimmsten Fall Valueproperty von null.

Was passiert, wenn Sie mit Intellisense über eine ConfigurationSection fahren und die Value-Eigenschaft betrachten, lautet: Jeder Konfig-Provider wurde durchsucht, und es wurde kein Schlüssel mit "MyConfig" gefunden, dessen primitiver Wert in eine Zeichenfolge zurückgegeben wurde . 

Sie müssen mindestens anrufen:

services.Configure<MyConfigOptions>(configuration.GetSection("MyConfig"));
services.AddSingleton(cfg => cfg.GetService<IOptions<MyConfigOptions>>().Value);

um es in Ihre App als C # -Objekt einzuspielen. Andernfalls rufen Sie einzelne Werte mit dem Doppelpunkt ["MyConfig:ConfigA"]-Trennzeichen oder mit var mySection = this.Configuration.GetSection("MyConfig")["ConfigA"]; auf, die zwar redundant ist, aber nur veranschaulicht, dass Primitive abgerufen werden.

Um an C # -Objekte zu binden und sie einzufügen, habe ich die folgende Erweiterungsmethode erstellt:

public static class IServiceCollectionExtensions
{
    public static IServiceCollection AddConfigOptions<TOptions>(this IServiceCollection services,
        IConfiguration configuration, string section) where TOptions : class, new()
    {
        services.Configure<TOptions>(configuration.GetSection(section));
        services.AddSingleton(cfg => cfg.GetService<IOptions<TOptions>>().Value);
        return services;
    }
}

was kann man so nennen:

public class Startup
{
    public Startup(IConfiguration configuration) => Configuration = configuration;

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddConfigOptions<EmailOptions>(Configuration, "Email")

und so gespritzt:

public class EmailSender : IEmailSender
{
    private EmailOptions _emailOptions;

    public EmailSender(EmailOptions options) => _emailOptions = options;
12

Ich habe festgestellt, dass AspNetCore 2.0 in der Konfiguration so viel einfacher ist als 1.x.

Wenn Sie im Konstruktor Startup(IConfiguration configuration) einen Haltepunkt setzen, werden Sie feststellen, dass die Variable configuration etwa 5 Anbieter hat.

Die JsonConfigurationProvider ist der Anbieter, den Sie für die Datei appsettings.json interessieren. Sie werden jedoch wahrscheinlich bemerken, dass die Data-Eigenschaft einen Count=0 hat. Dies ist höchstwahrscheinlich darauf zurückzuführen, dass Ihre Anwendung in dem in JsonConfigurationProvider.Source.FileProvider.Root angegebenen Verzeichnis nach der Datei appsettings.json sucht (dies ist standardmäßig wwwroot).

Alles was ich getan habe, war wie folgt eine MSBuild-Aufgabe in die .csproj-Datei hinzuzufügen:

<Copy SourceFiles="appsettings.json" DestinationFolder="wwwroot" />

Und das schien perfekt zu funktionieren.

Dies ist offensichtlich nur bei local development hilfreich. Heutzutage ist es jedoch allgemein üblich, nie eine Konfiguration in einer Datei zu haben, zumal diese am Ende zu Ihrem Repo-Verlauf wird. Stattdessen werden bei der Bereitstellung Ihrer App bei den beiden heute gängigen Methoden Umgebungsvariablen verwendet, um Ihre Werte zu überschreiben, oder besser noch, einen Schlüssel-/Wertspeicher wie Konsul zu verwenden.

Außerdem sehe ich im Internet eine ganze Reihe fantastischer Beispiele zur Verwendung von services.Configure<>(), was in Ordnung ist, aber der Startup.cs verwendet bereits DI, um Werte in IConfiguration configuration einzugeben. Das bedeutet, dass IConfiguration bereits im IoC-Container von .NET core registriert ist. Dies bedeutet im Wesentlichen, dass Sie IConfiguration bereits in jeder anderen Klasse in Ihrer App verwenden können.

public JobsRepository(IConfiguration configuration)
{
    this.configA = configuration.GetSection("MyConfig:ConfigA").Value;
}
0
Adel Helal

In meinem Fall fehlte mir ein Paket:

Microsoft.Extensions.Configuration.Binder

Es ist in der Tat als subtiler Code-Kommentar in hier dokumentiert.

0
Bruno Garcia