Konfigurationsanbieter in .NET

Die Konfiguration in .NET kann mit Konfigurationsanbietern durchgeführt werden. Es gibt mehrere Typen von Anbietern, die auf verschiedenen Konfigurationsquellen basieren. In diesem Artikel werden alle unterschiedlichen Konfigurationsanbieter und ihre entsprechenden Quellen ausführlich erläutert.

Dateikonfigurationsanbieter

FileConfigurationProvider ist die Basisklasse für das Laden einer Konfiguration aus dem Dateisystem. Die folgenden Konfigurationsanbieter leiten sich vom FileConfigurationProvider ab:

JSON-Konfigurationsanbieter

Die JsonConfigurationProvider-Klasse lädt die Konfiguration aus einer JSON-Datei. Installieren Sie das NuGet-Paket Microsoft.Extensions.Configuration.Json.

Überladungen können Folgendes angeben:

  • Ob die Datei optional ist
  • Ob die Konfiguration bei Dateiänderungen neu geladen wird

Betrachten Sie folgenden Code:

using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

namespace ConsoleJson.Example
{
    class Program
    {
        static async Task Main(string[] args)
        {
            using IHost host = CreateHostBuilder(args).Build();

            // Application code should start here.

            await host.RunAsync();
        }

        static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((hostingContext, configuration) =>
                {
                    configuration.Sources.Clear();

                    IHostEnvironment env = hostingContext.HostingEnvironment;

                    configuration
                        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", true, true);

                    IConfigurationRoot configurationRoot = configuration.Build();

                    TransientFaultHandlingOptions options = new();
                    configurationRoot.GetSection(nameof(TransientFaultHandlingOptions))
                                     .Bind(options);

                    Console.WriteLine($"TransientFaultHandlingOptions.Enabled={options.Enabled}");
                    Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={options.AutoRetryDelay}");
                });
    }
}

Der vorangehende Code:

  • Löscht alle vorhandenen Konfigurationsanbieter, die in der CreateDefaultBuilder(String[])-Methode standardmäßig hinzugefügt wurden
  • Konfiguriert den JSON-Konfigurationsanbieter so, dass die appsettings.json- und appsettings.Environment.json-Dateien mit den folgenden Optionen geladen werden:
    • optional: true: Die Datei ist optional.
    • reloadOnChange: true : Die Datei wird erneut geladen, wenn Änderungen gespeichert werden.

Die JSON-Einstellungen werden durch Einstellungen im Umgebungsvariablen-Konfigurationsanbieter und im Befehlszeilen-Konfigurationsanbieter überschrieben.

Eine appsettings.json-Beispieldatei mit unterschiedliche Konfigurationseinstellungen geht wie folgt vor:

{
    "SecretKey": "Secret key value",
    "TransientFaultHandlingOptions": {
        "Enabled": true,
        "AutoRetryDelay": "00:00:07"
    },
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        }
    }
}

Sie können nach Hinzufügen der Konfigurationsanbieter über die IConfigurationBuilder-Instanz IConfigurationBuilder.Build() aufrufen, um das IConfigurationRoot-Objekt abzurufen. Der Konfigurationsstamm stellt den Stamm einer Konfigurationshierarchie dar. Abschnitte aus der Konfiguration können an Instanzen von .NET-Objekten gebunden werden und später über Dependency Injection als IOptions<TOptions> bereitgestellt werden.

Sehen Sie sich die TransientFaultHandlingOptions-Klasse in der folgenden Definition an:

using System;

namespace ConsoleJson.Example
{
    public class TransientFaultHandlingOptions
    {
        public bool Enabled { get; set; }
        public TimeSpan AutoRetryDelay { get; set; }
    }
}

Der folgende Code erstellt den Konfigurationsstamm, bindet einen Abschnitt an den TransientFaultHandlingOptions-Klassentyp und gibt die gebundenen Werte im Konsolenfenster aus:

IConfigurationRoot configurationRoot = configuration.Build();

TransientFaultHandlingOptions options = new();
configurationRoot.GetSection(nameof(TransientFaultHandlingOptions))
                 .Bind(options);

Console.WriteLine($"TransientFaultHandlingOptions.Enabled={options.Enabled}");
Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={options.AutoRetryDelay}");

Die Anwendung schreibt dann die folgende Beispielausgabe:

// Sample output:
//    TransientFaultHandlingOptions.Enabled=True
//    TransientFaultHandlingOptions.AutoRetryDelay=00:00:07

XML-Konfigurationsanbieter

Die XmlConfigurationProvider-Klasse lädt die Konfiguration aus einer XML-Datei zur Laufzeit. Installieren Sie das NuGet-Paket Microsoft.Extensions.Configuration.Xml.

Im folgenden Code wird die Konfiguration von XML-Dateien mithilfe des XML-Konfigurationsanbieters veranschaulicht.

using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

namespace ConsoleXml.Example
{
    class Program
    {
        static async Task Main(string[] args)
        {
            using IHost host = CreateHostBuilder(args).Build();

            // Application code should start here.

            await host.RunAsync();
        }

        static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((hostingContext, configuration) =>
                {
                    configuration.Sources.Clear();

                    configuration
                        .AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true)
                        .AddXmlFile("repeating-example.xml", optional: true, reloadOnChange: true);

                    configuration.AddEnvironmentVariables();

                    if (args is { Length: > 0 })
                    {
                        configuration.AddCommandLine(args);
                    }
                });
    }
}

Der obige Code:

  • Löscht alle vorhandenen Konfigurationsanbieter, die in der CreateDefaultBuilder(String[])-Methode standardmäßig hinzugefügt wurden
  • Konfiguriert den XML-Konfigurationsanbieter zum Laden der appsettings.xml- und repeating-example.xml-Dateien mit den folgenden Optionen:
    • optional: true: Die Datei ist optional.
    • reloadOnChange: true : Die Datei wird erneut geladen, wenn Änderungen gespeichert werden.
  • Konfiguriert den Konfigurationsanbieter für Umgebungsvariablen
  • Konfiguriert den Konfigurationsanbieter für die Befehlszeile, wenn args Argumente enthält

Die XML-Einstellungen werden durch Einstellungen im Umgebungsvariablen-Konfigurationsanbieter und im Befehlszeilen-Konfigurationsanbieter überschrieben.

Eine appsettings.xml-Beispieldatei mit unterschiedliche Konfigurationseinstellungen geht wie folgt vor:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <SecretKey>Secret key value</SecretKey>
  <TransientFaultHandlingOptions>
    <Enabled>true</Enabled>
    <AutoRetryDelay>00:00:07</AutoRetryDelay>
  </TransientFaultHandlingOptions>
  <Logging>
    <LogLevel>
      <Default>Information</Default>
      <Microsoft>Warning</Microsoft>
    </LogLevel>
  </Logging>
</configuration>

Fügen Sie in .NET 5 und früheren Versionen das name-Attribut hinzu, um sich wiederholende Elemente zu unterscheiden, die den gleichen Elementnamen verwenden. In .NET 6 und höher werden sich wiederholende Elemente vom XML-Konfigurationsanbieter automatisch indiziert. Das bedeutet, dass Sie das name-Attribut nicht angeben müssen, es sei denn, Sie möchten den Index „0“ im Schlüssel und es gibt nur ein Element.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <section name="section0">
    <key name="key0">value 00</key>
    <key name="key1">value 01</key>
  </section>
  <section name="section1">
    <key name="key0">value 10</key>
    <key name="key1">value 11</key>
  </section>
</configuration>

Der folgende Code liest die vorherige Konfigurationsdatei und zeigt die Schlüssel und Werte an:

IConfigurationRoot configurationRoot = configuration.Build();

string key00 = "section:section0:key:key0";
string key01 = "section:section0:key:key1";
string key10 = "section:section1:key:key0";
string key11 = "section:section1:key:key1";

string val00 = configurationRoot[key00];
string val01 = configurationRoot[key01];
string val10 = configurationRoot[key10];
string val11 = configurationRoot[key11];

Console.WriteLine($"{key00} = {val00}");
Console.WriteLine($"{key01} = {val01}");
Console.WriteLine($"{key10} = {val10}");
Console.WriteLine($"{key10} = {val11}");

Die Anwendung schreibt dann die folgende Beispielausgabe:

// Sample output:
//    section:section0:key:key0 = value 00
//    section:section0:key:key1 = value 01
//    section:section1:key:key0 = value 10
//    section:section1:key:key0 = value 11

Mit Attributen können Werte bereitgestellt werden:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <key attribute="value" />
  <section>
    <key attribute="value" />
  </section>
</configuration>

Die vorherige Konfigurationsdatei lädt die folgenden Schlüssel mit value:

  • key:attribute
  • section:key:attribute

INI-Konfigurationsanbieter

Die IniConfigurationProvider-Klasse lädt die Konfiguration aus einer INI-Datei zur Laufzeit. Installieren Sie das NuGet-Paket Microsoft.Extensions.Configuration.Ini.

Der folgende Code löscht alle Konfigurationsanbieter und fügt IniConfigurationProvider mit zwei INI-Dateien als Quelle hinzu:

using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

namespace ConsoleIni.Example
{
    class Program
    {
        static async Task Main(string[] args)
        {
            using IHost host = CreateHostBuilder(args).Build();

            // Application code should start here.

            await host.RunAsync();
        }

        static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((hostingContext, configuration) => 
                {
                    configuration.Sources.Clear();

                    IHostEnvironment env = hostingContext.HostingEnvironment;

                    configuration
                        .AddIniFile("appsettings.ini", optional: true, reloadOnChange: true)
                        .AddIniFile($"appsettings.{env.EnvironmentName}.ini", true, true);

                    foreach ((string key, string value) in
                        configuration.Build().AsEnumerable().Where(t => t.Value is not null))
                    {
                        Console.WriteLine($"{key}={value}");
                    }
                });
    }
}

Eine appsettings.ini-Beispieldatei mit unterschiedliche Konfigurationseinstellungen geht wie folgt vor:

SecretKey="Secret key value"

[TransientFaultHandlingOptions]
Enabled=True
AutoRetryDelay="00:00:07"

[Logging:LogLevel]
Default=Information
Microsoft=Warning

Der folgende Code zeigt die vorangehenden Konfigurationseinstellungen an, indem sie in das Konsolenfenster geschrieben wird:

foreach ((string key, string value) in
    configuration.Build().AsEnumerable().Where(t => t.Value is not null))
{
    Console.WriteLine($"{key}={value}");
}

Die Anwendung schreibt dann die folgende Beispielausgabe:

// Sample output:
//    TransientFaultHandlingOptions:Enabled=True
//    TransientFaultHandlingOptions:AutoRetryDelay=00:00:07
//    SecretKey=Secret key value
//    Logging:LogLevel:Microsoft=Warning
//    Logging:LogLevel:Default=Information

Konfigurationsanbieter für Umgebungsvariablen

Bei Verwendung der Standardkonfiguration lädt der EnvironmentVariablesConfigurationProvider die Konfiguration aus Schlüssel-Wert-Paaren der Umgebungsvariablen, nachdem appsettings.json, appsettings. Environment .json und Secret Manager gelesen wurden. Daher überschreiben aus der Umgebung gelesene Schlüsselwerte Werte, die aus appsettings.json, appsettings. Environment .json und Secret Manager gelesen wurden.

Das Trennzeichen : funktioniert nicht auf allen Plattformen mit den hierarchischen Schlüsseln von Umgebungsvariablen. Der doppelte Unterstrich (__) wird auf allen Plattformen automatisch durch einen : ersetzt. Das Trennzeichen : wird beispielsweise nicht von Bash unterstützt, __ hingegen schon.

Die folgenden set-Befehle:

  • Legen die Umgebungsschlüssel und -werte des vorangehenden Beispiels unter Windows fest.
  • Testen Sie die Einstellungen, indem Sie die Standardwerte ändern. Der dotnet run-Befehl muss im Projektverzeichnis ausgeführt werden.
set SecretKey="Secret key from environment"
set TransientFaultHandlingOptions__Enabled="true"
set TransientFaultHandlingOptions__AutoRetryDelay="00:00:13"

dotnet run

Die obigen Umgebungseinstellungen:

  • Werden nur in Prozessen festgelegt, die über das Befehlsfenster gestartet werden, in dem sie festgelegt wurden.
  • Werden nicht von Web-Apps gelesen, die mit Visual Studio gestartet wurden

Mit Visual Studio 2019 16.10 Preview 4 und höher können Sie Umgebungsvariablen über das Dialogfeld Startprofile angeben.

Dialogfeld „Startprofile“ mit Umgebungsvariablen

Die folgenden setx-Befehle können zum Festlegen der Umgebungsschlüssel und -werte unter Windows verwendet werden. Anders als set werden setx-Einstellungen beibehalten. /M legt die Variable in der Systemumgebung fest. Wenn der /M-Schalter nicht verwendet wird, wird eine Benutzerumgebungsvariable festgelegt.

setx SecretKey "Secret key from setx environment" /M
setx TransientFaultHandlingOptions__Enabled "true" /M
setx TransientFaultHandlingOptions__AutoRetryDelay "00:00:05" /M

dotnet run

Testen Sie wie folgt, ob die obigen Befehle appsettings.json und appsettings. Environment .json überschreiben:

  • Mit Visual Studio: Beenden Sie Visual Studio, und starten Sie dann Visual Studio neu.
  • Mit der Befehlszeilenschnittstelle: Starten Sie ein neues Befehlsfenster, und geben Sie dotnet run ein.

Rufen Sie AddEnvironmentVariables mit einer Zeichenfolge auf, um ein Präfix für Umgebungsvariablen anzugeben:

using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

namespace ConsoleEnvironment.Example
{
    class Program
    {
        static async Task Main(string[] args)
        {
            using IHost host = CreateHostBuilder(args).Build();

            // Application code should start here.

            await host.RunAsync();
        }

        static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((hostingContext, configuration) =>
                    configuration.AddEnvironmentVariables(
                        prefix: "CustomPrefix_"));
    }
}

Für den Code oben gilt:

  • config.AddEnvironmentVariables(prefix: "CustomPrefix_") wird nach den Standardkonfigurationsanbietern hinzugefügt. Ein Beispiel für das Festlegen der Reihenfolge der Konfigurationsanbieter finden Sie unter XML-Konfigurationsanbieter.
  • Umgebungsvariablen, die mit dem CustomPrefix_-Präfix festgelegt wurden, überschreiben die Standardkonfigurationsanbieter. Dies schließt Umgebungsvariablen ohne das Präfix ein.

Das Präfix wird beim Lesen der Schlüssel-Wert-Paare der Konfiguration entfernt.

Mit den folgenden Befehlen wird das benutzerdefinierte Präfix getestet:

set CustomPrefix__SecretKey="Secret key with CustomPrefix_ environment"
set CustomPrefix__TransientFaultHandlingOptions__Enabled=true
set CustomPrefix__TransientFaultHandlingOptions__AutoRetryDelay=00:00:21

dotnet run

Die Standardkonfiguration lädt Umgebungsvariablen und Befehlszeilenargumente, die das Präfix DOTNET_ aufweisen. Das Präfix DOTNET_wird von .NET zum Hosten und für die App-Konfiguration verwendet, jedoch nicht für die Benutzerkonfiguration.

Weitere Informationen zur Host- und App-Konfiguration finden Sie unter .NET Generic Host.

Wählen Sie in Azure App Service auf der Seite Einstellungen > Konfiguration die Option Neue Anwendungseinstellung aus. Anwendungseinstellungen von Azure App Service werden:

  • Im Ruhezustand verschlüsselt und über einen verschlüsselten Kanal übermittelt.
  • Als Umgebungsvariablen verfügbar gemacht.

Präfixe für Verbindungszeichenfolgen

Die Konfigurations-API verfügt über spezielle Verarbeitungsregeln für vier Umgebungsvariablen für Verbindungszeichenfolgen. Diese Verbindungszeichenfolgen sind beim Konfigurieren von Azure-Verbindungszeichenfolgen für die App-Umgebung beteiligt. Umgebungsvariablen mit den in der Tabelle aufgeführten Präfixen werden mit der Standardkonfiguration in die App geladen bzw. wenn kein Präfix für AddEnvironmentVariables bereitgestellt wird.

Präfix für Verbindungszeichenfolgen Anbieter
CUSTOMCONNSTR_ Benutzerdefinierter Anbieter
MYSQLCONNSTR_ MySQL
SQLAZURECONNSTR_ Azure SQL-Datenbank
SQLCONNSTR_ SQL Server

Wenn eine Umgebungsvariable entdeckt und mit einem der vier Präfixe aus der Tabelle in die Konfiguration geladen wird, tritt Folgendes ein:

  • Der Konfigurationsschlüssel wird durch Entfernen des Umgebungsvariablenpräfixes und Hinzufügen eines Konfigurationsschlüsselabschnitts (ConnectionStrings) erstellt.
  • Ein neues Konfigurations-Schlüssel-Wert-Paar wird erstellt, das den Datenbankverbindungsanbieter repräsentiert (mit Ausnahme des Präfixes CUSTOMCONNSTR_, für das kein Anbieter angegeben ist).
Umgebungsvariablenschlüssel Konvertierter Konfigurationsschlüssel Anbieterkonfigurationseintrag
CUSTOMCONNSTR_{KEY} ConnectionStrings:{KEY} Konfigurationseintrag wurde nicht erstellt.
MYSQLCONNSTR_{KEY} ConnectionStrings:{KEY} Schlüssel: ConnectionStrings:{KEY}_ProviderName:
Wert: MySql.Data.MySqlClient
SQLAZURECONNSTR_{KEY} ConnectionStrings:{KEY} Schlüssel: ConnectionStrings:{KEY}_ProviderName:
Wert: System.Data.SqlClient
SQLCONNSTR_{KEY} ConnectionStrings:{KEY} Schlüssel: ConnectionStrings:{KEY}_ProviderName:
Wert: System.Data.SqlClient

In „launchSettings.json“ festgelegte Umgebungsvariablen

Umgebungsvariablen, die in der Datei launchSettings.json festgelegt sind, überschreiben diejenigen, die in der Systemumgebung festgelegt sind.

Befehlszeilen-Konfigurationsanbieter

Bei Verwendung der Standard-Konfiguration lädt der CommandLineConfigurationProvider die Konfiguration aus den Schlüssel-Wert-Paaren des Befehlszeilenarguments nach den folgenden Konfigurationsquellen:

  • Dateien appsettings.json und appsettings.Environment.json.
  • App-Geheimnisse (Secret Manager) in der Development-Umgebung
  • Umgebungsvariablen.

Standardmäßig überschreiben in der Befehlszeile festgelegte Konfigurationswerte die Konfigurationswerte, die mit allen anderen Konfigurationsanbietern festgelegt wurden.

Mit Visual Studio 2019 16.10 Preview 4 und höher können Sie Befehlszeilenargumente über das Dialogfeld Startprofile angeben.

Dialogfeld „Startprofile“ mit Befehlszeilenargumenten

Befehlszeilenargumente

Der folgende Befehl legt Schlüssel und Werte unter Verwendung von = fest:

dotnet run SecretKey="Secret key from command line"

Der folgende Befehl legt Schlüssel und Werte unter Verwendung von / fest:

dotnet run /SecretKey "Secret key set from forward slash"

Der folgende Befehl legt Schlüssel und Werte unter Verwendung von -- fest:

dotnet run --SecretKey "Secret key set from double hyphen"

Der Schlüsselwert:

  • Muss auf = folgen, oder der Schlüssel muss das Präfix -- oder / aufweisen, wenn der Wert auf ein Leerzeichen folgt.
  • Ist nicht erforderlich, wenn = verwendet wird. Beispielsweise SomeKey=.

Kombinieren Sie in einem Befehl nicht Schlüssel-Wert-Paare des Befehlszeilenarguments, die = verwenden, mit Schlüssel-Wert-Paaren, die ein Leerzeichen verwenden.

Schlüssel-pro-Datei-Konfigurationsanbieter

KeyPerFileConfigurationProvider verwendet Verzeichnisdateien als Konfigurations-Schlüssel-Wert-Paare. Der Schlüssel ist der Dateiname. Der Wert ist der Inhalt der Datei. Der Schlüssel-pro-Datei-Konfigurationsanbieter wird in Docker-Hostingszenarios verwendet.

Um die Schlüssel-pro-Datei-Konfiguration zu aktivieren, rufen Sie die AddKeyPerFile-Erweiterungsmethode auf einer ConfigurationBuilder-Instanz auf. Der directoryPath zu den Dateien muss ein absoluter Pfad sein.

Überladungen geben Folgendes an:

  • Einen Action<KeyPerFileConfigurationSource>-Delegat, der die Quelle konfiguriert
  • Ob das Verzeichnis optional ist; und den Pfad zum Verzeichnis

Der doppelte Unterstrich (__) wird als Trennzeichen für Konfigurationsschlüssel in Dateinamen verwendet. Der Dateiname Logging__LogLevel__System erzeugt z.B. den Konfigurationsschlüssel Logging:LogLevel:System.

Rufen Sie ConfigureAppConfiguration beim Erstellen des Hosts auf, um die Konfiguration der App anzugeben:

.ConfigureAppConfiguration((_, configuration) =>
{
    var path = Path.Combine(
        Directory.GetCurrentDirectory(), "path/to/files");

    configuration.AddKeyPerFile(directoryPath: path, optional: true);
})

Speicherkonfigurationsanbieter

MemoryConfigurationProvider verwendet eine In-Memory-Sammlung für Konfigurations-Schlüssel-Wert-Paare.

Der folgende Code fügt eine Arbeitsspeichersammlung zum Konfigurationssystem hinzu:

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

namespace ConsoleMemory.Example
{
    class Program
    {
        static async Task Main(string[] args)
        {
            using IHost host = CreateHostBuilder(args).Build();

            // Application code should start here.

            await host.RunAsync();
        }

        static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((_, configuration) =>
                    configuration.AddInMemoryCollection(
                        new Dictionary<string, string>
                        {
                            ["SecretKey"] = "Dictionary MyKey Value",
                            ["TransientFaultHandlingOptions:Enabled"] = bool.TrueString,
                            ["TransientFaultHandlingOptions:AutoRetryDelay"] = "00:00:07",
                            ["Logging:LogLevel:Default"] = "Warning"
                        }));
    }
}

Im vorangehenden Code fügt MemoryConfigurationBuilderExtensions.AddInMemoryCollection(IConfigurationBuilder, IEnumerable<KeyValuePair<String,String>>) den Speicheranbieter nach den Standardkonfigurationsanbietern hinzu. Ein Beispiel für das Festlegen der Reihenfolge der Konfigurationsanbieter finden Sie unter XML-Konfigurationsanbieter.

Siehe auch