Konfiguration in ASP.NET Core

Von Rick Anderson und Kirk Larkin

Die Konfiguration in ASP.NET Core erfolgt mithilfe eines oder mehrerer Konfigurationsanbieter. Konfigurationsanbieter lesen Konfigurationsdaten aus Schlüssel-Wert-Paaren unter Verwendung verschiedener Konfigurationsquellen:

  • Einstellungsdateien, z. B. appsettings.json
  • Umgebungsvariablen
  • Azure Key Vault
  • Azure App Configuration
  • Befehlszeilenargumente
  • Benutzerdefinierte Anbieter (installiert oder erstellt)
  • Verzeichnisdateien
  • Speicherinterne .NET Objekte

Dieses Thema enthält Informationen zur Konfiguration in ASP.NET Core. Informationen zur Verwendung der Konfiguration in Konsolen-Apps finden Sie unter .NET-Konfiguration.

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)

Standardkonfiguration

ASP.NET Core-Web-Apps, die mit dotnet new oder Visual Studio erstellt wurden, generieren den folgenden Code:

var builder = WebApplication.CreateBuilder(args);

WebApplication.CreateBuilder Initialisiert eine neue Instanz der WebApplicationBuilder-Klasse mit vorkonfigurierten Standardwerten. Die initialisierte WebApplicationBuilder-Methode (builder) legt die Standardkonfiguration für die App in der folgenden Reihenfolge fest:

  1. ChainedConfigurationProvider: Fügt eine vorhandene IConfiguration als Quelle hinzu. Im Fall einer Standardkonfiguration wird die Host-Konfiguration hinzugefügt und als erste Quelle für die App- Konfiguration festgelegt.
  2. appsettings.json mithilfe des JSON-Konfigurationsanbieters
  3. appsettings. Environment .json mithilfe des JSON-Konfigurationsanbieters. Beispielsweise appsettings.Production_._json and appsettings.Development _._json.
  4. App-Geheimnisse, wenn die App in der Development-Umgebung ausgeführt wird
  5. Umgebungsvariablen, die den Umgebungsvariablen-Konfigurationsanbieter verwenden
  6. Befehlszeilenargumente, die den Befehlszeilen-Konfigurationsanbieter verwenden

Später hinzugefügte Konfigurationsanbieter überschreiben vorherige Schlüsseleinstellungen. Wenn beispielsweise MyKey sowohl unter appsettings.json als auch unter Umgebung festgelegt wird, wird der Umgebungswert verwendet. Bei Verwendung der Standardkonfigurationsanbieter überschreibt der Befehlszeilen-Konfigurationsanbieter alle anderen Anbieter.

Weitere Informationen zu CreateBuilder finden Sie unter Standardeinstellungen für den Generator.

Im folgenden Code werden die aktivierten Konfigurationsanbieter in der Reihenfolge angezeigt, in der sie hinzugefügt wurden:

public class Index2Model : PageModel
{
    private IConfigurationRoot ConfigRoot;

    public Index2Model(IConfiguration configRoot)
    {
        ConfigRoot = (IConfigurationRoot)configRoot;
    }

    public ContentResult OnGet()
    {           
        string str = "";
        foreach (var provider in ConfigRoot.Providers.ToList())
        {
            str += provider.ToString() + "\n";
        }

        return Content(str);
    }
}

appsettings.json

Betrachten Sie die folgende appsettings.json -Datei:

{
    "Position": {
        "Title": "Editor",
        "Name": "Joe Smith"
    },
    "MyKey": "My appsettings.json Value",
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        }
    },
    "AllowedHosts": "*"
}

Im folgenden Code aus dem Beispieldownload sind mehrere der vorherigen Konfigurationseinstellungen zu sehen:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

Der Standard-JsonConfigurationProvider lädt die Konfiguration in der folgenden Reihenfolge:

  1. appsettings.json
  2. appsettings. Environment .json: Beispielsweise die Dateien appsettings.Production_._json and appsettings.Development _._json. Die Umgebungsversion der Datei wird basierend auf IHostingEnvironment.EnvironmentName geladen. Weitere Informationen finden Sie unter Verwenden von mehreren Umgebungen in ASP.NET Core.

appsettings.Environment.json-Werte überschreiben Schlüssel in appsettings.json . Standardmäßig sind dies z. B.:

  • In der Entwicklung überschreibt die appsettings.*Development _._json-Konfiguration in appsettings.json gefundene Werte.
  • In der Produktion überschreibt die appsettings.Production _._json-Konfiguration in appsettings.json gefundene Werte. Dies ist beispielsweise bei der Bereitstellung der App in Azure der Fall.

Wenn ein Konfigurationswert garantiert werden muss, nutzen Sie die Informationen unter GetValue. Im vorherigen Beispiel werden nur Zeichenfolgen gelesen, und es wird kein Standardwert unterstützt.

Wenn die Standard-Konfiguration verwendet wird, werden die Dateien appsettings.json und appsettings. Environment .json mit reloadOnChange: true aktiviert. Änderungen an den Dateien appsettings.json und appsettings. Environment .json nach dem Start der App werden vom JSON-Konfigurationsanbieter gelesen.

Binden hierarchischer Konfigurationsdaten mit dem Optionsmuster

Die bevorzugte Methode für das Lesen zugehöriger Konfigurationswerte ist die Verwendung des Optionsmusters. Um z. B. die folgenden Konfigurationswerte zu lesen:

  "Position": {
    "Title": "Editor",
    "Name": "Joe Smith"
  }

Erstellen Sie die folgende neue PositionOptions-Klasse:

public class PositionOptions
{
    public const string Position = "Position";

    public string Title { get; set; } = String.Empty;
    public string Name { get; set; } = String.Empty;
}

Eine Optionsklasse:

  • Eine Optionsklasse muss nicht abstrakt sein und über einen öffentlichen parameterlosen Konstruktor verfügen.
  • Alle öffentlichen Lese-/Schreibeigenschaften des Typs sind gebunden.
  • Felder werden nicht gebunden. Im vorangehenden Code ist Position nicht gebunden. Die Position-Eigenschaft wird verwendet, sodass die Zeichenfolge "Position" nicht in der App hartcodiert werden muss, wenn die Klasse an einen Konfigurationsanbieter gebunden wird.

Der folgende Code

  • Ruft ConfigurationBinder.Bind auf, um die PositionOptions-Klasse an den Position-Abschnitt zu binden.
  • Zeigt die Position-Konfigurationsdaten an.
public class Test22Model : PageModel
{
    private readonly IConfiguration Configuration;

    public Test22Model(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var positionOptions = new PositionOptions();
        Configuration.GetSection(PositionOptions.Position).Bind(positionOptions);

        return Content($"Title: {positionOptions.Title} \n" +
                       $"Name: {positionOptions.Name}");
    }
}

Im vorangehenden Code werden standardmäßig Änderungen an der JSON-Konfigurationsdatei gelesen, nachdem die App gestartet wurde.

ConfigurationBinder.Get<T> bindet den angegebenen Typ und gibt ihn zurück. ConfigurationBinder.Get<T> ist möglicherweise praktischer als die Verwendung von ConfigurationBinder.Bind. Der folgende Code zeigt die Verwendung von ConfigurationBinder.Get<T> mit der PositionOptions-Klasse:

public class Test21Model : PageModel
{
    private readonly IConfiguration Configuration;
    public PositionOptions? positionOptions { get; private set; }

    public Test21Model(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {            
        positionOptions = Configuration.GetSection(PositionOptions.Position)
                                                     .Get<PositionOptions>();

        return Content($"Title: {positionOptions.Title} \n" +
                       $"Name: {positionOptions.Name}");
    }
}

Im vorangehenden Code werden standardmäßig Änderungen an der JSON-Konfigurationsdatei gelesen, nachdem die App gestartet wurde.

Eine alternative Vorgehensweise bei der Verwendung des Optionsmusters besteht darin, den Position-Abschnitt zu binden und ihn zum Dependency-Injection-Dienstcontainer hinzuzufügen. Im folgenden Code wird PositionOptions mit <xref:Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions.Configure_> zum Dienstcontainer hinzugefügt und an die Konfiguration gebunden:

using ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<PositionOptions>(
    builder.Configuration.GetSection(PositionOptions.Position));

var app = builder.Build();

Mithilfe des vorangehenden Codes liest der folgende Code die Positionsoptionen:

public class Test2Model : PageModel
{
    private readonly PositionOptions _options;

    public Test2Model(IOptions<PositionOptions> options)
    {
        _options = options.Value;
    }

    public ContentResult OnGet()
    {
        return Content($"Title: {_options.Title} \n" +
                       $"Name: {_options.Name}");
    }
}

Im vorangehenden Code werden Änderungen an der JSON-Konfigurationsdatei nach dem Start der App nicht gelesen. Verwenden Sie IOptionsSnapshot, um Änderungen lesen zu können, nachdem die App gestartet wurde.

Wenn die Standard-Konfiguration verwendet wird, werden die Dateien appsettings.json und appsettings. Environment .json mit reloadOnChange: true aktiviert. Änderungen an den Dateien appsettings.json und appsettings. Environment .json nach dem Start der App werden vom JSON-Konfigurationsanbieter gelesen.

Weitere Informationen zum Hinzufügen zusätzlicher JSON-Konfigurationsdateien finden Sie unter JSON-Konfigurationsanbieter in diesem Dokument.

Kombinieren von Dienstsammlungen

Folgendermaßen können Sie Dienste registrieren und Optionen konfigurieren:

using ConfigSample.Options;
using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<PositionOptions>(
    builder.Configuration.GetSection(PositionOptions.Position));
builder.Services.Configure<ColorOptions>(
    builder.Configuration.GetSection(ColorOptions.Color));

builder.Services.AddScoped<IMyDependency, MyDependency>();
builder.Services.AddScoped<IMyDependency2, MyDependency2>();

var app = builder.Build();

Ähnliche Registrierungsgruppen können in eine Erweiterungsmethode verschoben werden, um Dienste zu registrieren. Die Konfigurationsdienste werden beispielsweise folgender Klasse hinzugefügt:

using ConfigSample.Options;
using Microsoft.Extensions.Configuration;

namespace Microsoft.Extensions.DependencyInjection
{
    public static class MyConfigServiceCollectionExtensions
    {
        public static IServiceCollection AddConfig(
             this IServiceCollection services, IConfiguration config)
        {
            services.Configure<PositionOptions>(
                config.GetSection(PositionOptions.Position));
            services.Configure<ColorOptions>(
                config.GetSection(ColorOptions.Color));

            return services;
        }
    }
}

Die verbleibenden Dienste werden in einer ähnlichen Klasse registriert. Der folgende Code verwendet die neuen Erweiterungsmethoden, um die Dienste zu registrieren:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services
    .AddConfig(builder.Configuration)
    .AddMyDependencyGroup();

builder.Services.AddRazorPages();

var app = builder.Build();

Hinweis: Jede services.Add{GROUP_NAME}-Erweiterungsmethode fügt Dienste hinzu und konfiguriert diese möglicherweise. Beispielsweise fügt AddControllersWithViews den MVC-Controller für Dienste mit den erforderlichen Ansichten hinzu, und AddRazorPages fügt die für Razor Pages benötigten Dienste hinzu. Bei Apps sollte die Namenskonvention zum Erstellen von Erweiterungsmethoden im Microsoft.Extensions.DependencyInjection-Namespace befolgt werden. Erstellen von Erweiterungsmethoden im Microsoft.Extensions.DependencyInjection-Namespace:

  • Kapselt Gruppen von Dienstregistrierungen.
  • Bietet komfortablen IntelliSense-Zugriff auf den Dienst.

Sicherheit und Benutzergeheimnisse

Richtlinien für Konfigurationsdaten:

  • Speichern Sie nie Kennwörter oder andere vertrauliche Daten im Konfigurationsanbietercode oder in Nur-Text-Konfigurationsdateien. Das Secret Manager-Tool kann zum Speichern von Geheimnissen in der Entwicklungsumgebung verwendet werden.
  • Verwenden Sie keine Produktionsgeheimnisse in Entwicklungs- oder Testumgebungen.
  • Geben Sie Geheimnisse außerhalb des Projekts an, damit sie nicht versehentlich in ein Quellcoderepository übernommen werden können.

Im Standardmodell wird die Quelle der Benutzergeheimniskonfiguration nach den Quellen für die JSON-Konfiguration registriert. Daher haben geheime Benutzerschlüssel Vorrang vor Schlüssel in appsettings.json und appsettings. Environment .json.

Weitere Informationen zum Speichern von Kennwörtern oder anderen vertraulichen Daten:

Azure Key Vault speichert App-Geheimnisse für ASP.NET Core-Apps auf sichere Weise. Weitere Informationen finden Sie unter Azure Key Vault-Konfigurationsanbieter in ASP.NET Core.

Umgebungsvariablen

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

Das Trennzeichen : funktioniert nicht auf allen Plattformen mit den hierarchischen Schlüsseln von Umgebungsvariablen. Der doppelte Unterstrich __:

  • wird auf allen Plattformen unterstützt. Das Trennzeichen : wird beispielsweise nicht von Bash unterstützt, __ hingegen schon.
  • automatisch durch : ersetzt.

Die folgenden set-Befehle:

  • Legen die Umgebungsschlüssel und -werte des vorangehenden Beispiels unter Windows fest.
  • Testen die Einstellungen bei Verwendung des Beispieldownloads. Der dotnet run-Befehl muss im Projektverzeichnis ausgeführt werden.
set MyKey="My key from Environment"
set Position__Title=Environment_Editor
set Position__Name=Environment_Rick
dotnet run

Die obigen Umgebungseinstellungen:

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

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 MyKey "My key from setx Environment" /M
setx Position__Title Environment_Editor /M
setx Position__Name Environment_Rick /M

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:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Configuration.AddEnvironmentVariables(prefix: "MyCustomPrefix_");

var app = builder.Build();

Für den Code oben gilt:

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 MyCustomPrefix_MyKey="My key with MyCustomPrefix_ Environment"
set MyCustomPrefix_Position__Title=Editor_with_customPrefix
set MyCustomPrefix_Position__Name=Environment_Rick_cp
dotnet run

Die Standardkonfiguration lädt Umgebungsvariablen und Befehlszeilenargumente, die das Präfix DOTNET_ und ASPNETCORE_ aufweisen. Die Präfixe DOTNET_ und ASPNETCORE_ werden von ASP.NET Core für die Host- und App-Konfiguration, jedoch nicht für die Benutzerkonfiguration verwendet. 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.

Weitere Informationen finden Sie unter Azure-Apps: Überschreiben der App-Konfiguration im Azure-Portal.

Informationen zu Azure-Datenbankverbindungszeichenfolgen finden Sie unter Präfixe für Verbindungszeichenfolgen.

Benennen von Umgebungsvariablen

Umgebungsvariablennamen entsprechen der Struktur einer appsettings.json -Datei. Die Elemente in der Hierarchie werden durch einen doppelten Unterstrich (vorzugsweise) oder einen Doppelpunkt getrennt. Wenn die Elementstruktur ein Array enthält, sollte der Arrayindex als zusätzlicher Elementname in diesem Pfad behandelt werden. Schauen Sie sich die folgende appsettings.json -Datei und ihre entsprechenden Werte an, die als Umgebungsvariablen dargestellt werden.

appsettings.json

{
    "SmtpServer": "smtp.example.com",
    "Logging": [
        {
            "Name": "ToEmail",
            "Level": "Critical",
            "Args": {
                "FromAddress": "MySystem@example.com",
                "ToAddress": "SRE@example.com"
            }
        },
        {
            "Name": "ToConsole",
            "Level": "Information"
        }
    ]
}

Umgebungsvariablen

setx SmtpServer=smtp.example.com
setx Logging__0__Name=ToEmail
setx Logging__0__Level=Critical
setx Logging__0__Args__FromAddress=MySystem@example.com
setx Logging__0__Args__ToAddress=SRE@example.com
setx Logging__1__Name=ToConsole
setx Logging__1__Level=Information

In generierter Datei „launchSettings.json“ festgelegte Umgebungsvariablen

Umgebungsvariablen, die in der Datei launchSettings.json festgelegt sind, überschreiben diejenigen, die in der Systemumgebung festgelegt sind. Die ASP.NET Core-Webvorlagen generieren z. B. eine launchSettings.json-Datei, mit der die Endpunktkonfiguration auf Folgendes festgelegt wird:

"applicationUrl": "https://localhost:5001;http://localhost:5000"

Beim Konfigurieren der applicationUrl wird die ASPNETCORE_URLS-Umgebungsvariable festgelegt, und die in der Umgebung festgelegten Werte werden überschrieben.

Umgebungsvariablen unter Linux mit einem Escapezeichen versehen

Unter Linux muss der Wert von URL-Umgebungsvariablen mit einem Escapezeichen versehen werden, damit systemd ihn analysieren kann. Verwenden Sie das Linux-Tool systemd-escape, das http:--localhost:5001 erzeugt.

groot@terminus:~$ systemd-escape http://localhost:5001
http:--localhost:5001

Anzeigen von Umgebungsvariablen

Der folgende Code zeigt die Umgebungsvariablen und Werte beim Anwendungsstart an, was beim Debuggen von Umgebungseinstellungen hilfreich sein kann:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

var config = app.Services.GetRequiredService<IConfiguration>();

foreach (var c in config.AsEnumerable())
{
    Console.WriteLine(c.Key + " = " + c.Value);
}

Befehlszeile

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

  • In den Dateien appsettings.json und appsettings.Environment.json
  • App-Geheimnisse in der Entwicklungsumgebung.
  • Umgebungsvariablen.

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

Befehlszeilenargumente

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

dotnet run MyKey="My key from command line" Position:Title=Cmd Position:Name=Cmd_Rick

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

dotnet run /MyKey "Using /" /Position:Title=Cmd_ /Position:Name=Cmd_Rick

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

dotnet run --MyKey "Using --" --Position:Title=Cmd-- --Position:Name=Cmd--Rick

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 MySetting=.

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

Switchmappings

Switchmappings erlauben das Angeben einer Logik zum Ersetzen von Schlüsselnamen. Stellen Sie ein Wörterbuch mit Switchersetzungen für die AddCommandLine-Methode bereit.

Wenn das Switchmappingwörterbuch verwendet wird, wird das Wörterbuch für Schlüssel, die dem von einem Befehlszeilenargument angegebenen Schlüssel entsprechen, überprüft. Wenn der Befehlszeilenschlüssel im Wörterbuch gefunden wird, wird der Wörterbuchwert zum Festlegen des Schlüssel-Wert-Paares in der App-Konfiguration zurückgegeben. Ein Switchmapping ist für jeden Befehlszeilenschlüssel erforderlich, dem ein einzelner Gedankenstrich (-) vorangestellt ist.

Regeln für Schlüssel von Switchmappingwörterbüchern:

  • Switches müssen mit - oder -- beginnen.
  • Das Switchmappingwörterbuch darf keine doppelten Schlüssel enthalten.

Wenn Sie ein Switchmappingwörterbuch verwenden möchten, übergeben Sie es an den AddCommandLine-Abruf:


var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

var switchMappings = new Dictionary<string, string>()
         {
             { "-k1", "key1" },
             { "-k2", "key2" },
             { "--alt3", "key3" },
             { "--alt4", "key4" },
             { "--alt5", "key5" },
             { "--alt6", "key6" },
         };

builder.Configuration.AddCommandLine(args, switchMappings);

var app = builder.Build();

Mit dem folgenden Befehl kann die Schlüsselersetzung getestet werden:

dotnet run -k1 value1 -k2 value2 --alt3=value2 /alt4=value3 --alt5 value5 /alt6 value6

Der folgende Code zeigt die Schlüsselwerte für die ersetzten Schlüssel:

public class Test3Model : PageModel
{
    private readonly IConfiguration Config;

    public Test3Model(IConfiguration configuration)
    {
        Config = configuration;
    }

    public ContentResult OnGet()
    {
        return Content(
                $"Key1: '{Config["Key1"]}'\n" +
                $"Key2: '{Config["Key2"]}'\n" +
                $"Key3: '{Config["Key3"]}'\n" +
                $"Key4: '{Config["Key4"]}'\n" +
                $"Key5: '{Config["Key5"]}'\n" +
                $"Key6: '{Config["Key6"]}'");
    }
}

Bei Apps, die Switchmappings verwenden, sollten im CreateDefaultBuilder-Aufruf keine Argumente übergeben werden. Der AddCommandLine-Aufruf der CreateDefaultBuilder-Methode umfasst keine zugeordneten Switches, und das Switchmappingwörterbuch kann nicht an CreateDefaultBuilder übergeben werden. Die Lösung besteht nicht darin, die Argumente an CreateDefaultBuilder zu übergeben, sondern der AddCommandLine-Methode der ConfigurationBuilder-Methode zu erlauben, sowohl die Argumente als auch das Switchmappingwörterbuch zu verarbeiten.

Festlegen von Umgebungs- und Befehlszeilenargumenten mit Visual Studio

Umgebungs- und Befehlszeilenargumente können im Dialogfeld „Startprofile“ in Visual Studio festgelegt werden:

  • Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie Eigenschaften aus.
  • Wählen Sie die Registerkarte Debuggen > Allgemein aus, und klicken Sie auf die Option Open debug launch profiles UI (Benutzeroberfläche für Debugstartprofile öffnen).

Hierarchische Konfigurationsdaten

Die Konfigurations-API liest hierarchische Konfigurationsdaten, indem sie die hierarchischen Daten mit einem Trennzeichen in den Konfigurationsschlüsseln vereinfacht.

Der Beispieldownload enthält die folgende Datei appsettings.json :

{
    "Position": {
        "Title": "Editor",
        "Name": "Joe Smith"
    },
    "MyKey": "My appsettings.json Value",
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        }
    },
    "AllowedHosts": "*"
}

Der folgende Code aus dem Beispieldownload zeigt einige der Konfigurationseinstellungen:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

Die bevorzugte Methode zum Lesen hierarchischer Konfigurationsdaten ist die Verwendung des Optionsmusters. Weitere Informationen finden Sie unter Binden hierarchischer Konfigurationsdaten in diesem Dokument.

Mit den Methoden GetSection und GetChildren können Abschnitte und untergeordnete Abschnittelemente in den Konfigurationsdaten isoliert werden. Diese Methoden werden später im Abschnitt GetSection, GetChildren und Exists beschrieben.

Konfigurationsschlüssel und -werte

Konfigurationsschlüssel:

  • Die Groß-/Kleinschreibung wird nicht berücksichtigt. Beispielsweise verweisen ConnectionString und connectionstring auf denselben Schlüssel.
  • Wenn ein Schlüssel und ein Wert in mehreren Konfigurationsanbietern festgelegt ist, wird der Wert des zuletzt hinzugefügten Anbieters verwendet. Weitere Informationen finden Sie unter Standardkonfiguration.
  • Hierarchische Schlüssel
    • Innerhalb der Konfigurations-API funktioniert ein Doppelpunkt (:) als Trennzeichen auf allen Plattformen.
    • In Umgebungsvariablen funktioniert ein Doppelpunkt als Trennzeichen ggf. nicht auf allen Plattformen. Ein doppelter Unterstrich (__) wird von allen Plattformen unterstützt und automatisch in einen Doppelpunkt (:) umgewandelt.
    • In Azure Key Vault verwenden hierarchische Schlüssel -- als Trennzeichen. Der Azure Key Vault-Konfigurationsanbieter ersetzt -- automatisch durch :, wenn die Geheimnisse in die Konfiguration der App geladen werden.
  • ConfigurationBinder unterstützt das Binden von Arrays an Objekte mit Arrayindizes in Konfigurationsschlüsseln. Die Arraybindung wird im Abschnitt Binden eines Arrays an eine Klasse beschrieben.

Konfigurationswerte:

  • Sind Zeichenfolgen.
  • NULL-Werte können nicht in einer Konfiguration gespeichert oder an Objekte gebunden werden.

Konfigurationsanbieter

Die folgende Tabelle zeigt die für ASP.NET Core-Apps verfügbaren Konfigurationsanbieter.

Anbieter Bereitstellung der Konfiguration über
Azure Key Vault-Konfigurationsanbieter Azure Key Vault
Azure-App-Konfigurationsanbieter Azure App Configuration
Befehlszeilen-Konfigurationsanbieter Befehlszeilenparameter
Benutzerdefinierter Konfigurationsanbieter Benutzerdefinierte Quelle
Umgebungsvariablen-Konfigurationsanbieter Umgebungsvariablen
Dateikonfigurationsanbieter INI-, JSON- und XML-Dateien
Schlüssel-pro-Datei-Konfigurationsanbieter Verzeichnisdateien
Speicherkonfigurationsanbieter In-Memory-Sammlungen
Benutzergeheimnisse Datei im Benutzerprofilverzeichnis

Konfigurationsquellen werden in der Reihenfolge gelesen, in der ihre Konfigurationsanbieter angegeben sind. Ordnen Sie die Konfigurationsanbieter im Code so an, dass sie den Prioritäten für die zugrunde liegenden Konfigurationsquellen entsprechen, die für die App erforderlich sind.

Eine typische Konfigurationsanbietersequenz ist:

  1. appsettings.json
  2. appsettings.Environment.json
  3. Benutzergeheimnisse
  4. Umgebungsvariablen, die den Umgebungsvariablen-Konfigurationsanbieter verwenden
  5. Befehlszeilenargumente, die den Befehlszeilen-Konfigurationsanbieter verwenden

In der Regel werden Befehlszeilen-Konfigurationsanbieter in einer Reihe von Anbietern an letzter Stelle hinzugefügt, damit Befehlszeilenargumente die von anderen Anbietern festgelegte Konfiguration überschreiben können.

Die obige Sequenz von Anbietern wird in der Standardkonfiguration verwendet.

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

Dateikonfigurationsanbieter

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

INI-Konfigurationsanbieter

IniConfigurationProvider lädt während der Laufzeit die Konfiguration aus den Schlüssel-Wert-Paaren der INI-Datei.

Mit dem folgenden Code werden alle Konfigurationsanbieter gelöscht und mehrere Konfigurationsanbieter hinzugefügt: [!code-csharp]

Im obigen Code werden Einstellungen in den Dateien MyIniConfig.ini und MyIniConfig.Environment.ini überschrieben durch Einstellungen im:

Der Beispieldownload enthält die folgende Datei MyIniConfig.ini:

MyKey="MyIniConfig.ini Value"

[Position]
Title="My INI Config title"
Name="My INI Config name"

[Logging:LogLevel]
Default=Information
Microsoft=Warning

Im folgenden Code aus dem Beispieldownload sind mehrere der vorherigen Konfigurationseinstellungen zu sehen:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

JSON-Konfigurationsanbieter

Der JsonConfigurationProvider lädt die Konfiguration aus den Schlüssel-Wert-Paaren der JSON-Datei.

Überladungen können Folgendes angeben:

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

Betrachten Sie folgenden Code:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Host.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.AddJsonFile("MyConfig.json",
                       optional: true,
                       reloadOnChange: true);
});

builder.Services.AddRazorPages();

var app = builder.Build();

Der vorangehende Code:

In der Regel möchten Sie nicht, dass eine benutzerdefinierte JSON-Datei Werte überschreibt, die im Umgebungsvariablen-Konfigurationsanbieter und im Befehlszeilen-Konfigurationsanbieter festgelegt sind.

XML-Konfigurationsanbieter

XmlConfigurationProvider lädt während der Laufzeit die Konfiguration aus den Schlüssel-Wert-Paaren der XML-Datei.

Mit dem folgenden Code werden alle Konfigurationsanbieter gelöscht und mehrere Konfigurationsanbieter hinzugefügt:

var builder = WebApplication.CreateBuilder(args);

builder.Host.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.Sources.Clear();

    var env = hostingContext.HostingEnvironment;

    config.AddXmlFile("MyXMLFile.xml", optional: true, reloadOnChange: true)
          .AddXmlFile($"MyXMLFile.{env.EnvironmentName}.xml",
                         optional: true, reloadOnChange: true);

    config.AddEnvironmentVariables();

    if (args != null)
    {
        config.AddCommandLine(args);
    }
});

builder.Services.AddRazorPages();

var app = builder.Build();

Im obigen Code werden Einstellungen in den Dateien MyXMLFile.xml und MyXMLFile.Environment.xml überschrieben durch Einstellungen im:

Der Beispieldownload enthält die folgende Datei MyXMLFile.xml:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <MyKey>MyXMLFile Value</MyKey>
  <Position>
    <Title>Title from  MyXMLFile</Title>
    <Name>Name from MyXMLFile</Name>
  </Position>
  <Logging>
    <LogLevel>
      <Default>Information</Default>
      <Microsoft>Warning</Microsoft>
    </LogLevel>
  </Logging>
</configuration>

Im folgenden Code aus dem Beispieldownload sind mehrere der vorherigen Konfigurationseinstellungen zu sehen:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

Wiederholte Elemente mit den gleichen Elementnamen funktionieren, wenn das name-Attribut zur Unterscheidung der Elemente verwendet wird:

<?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:

public class IndexModel : PageModel
{
    private readonly IConfiguration Configuration;

    public IndexModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var key00 = "section:section0:key:key0";
        var key01 = "section:section0:key:key1";
        var key10 = "section:section1:key:key0";
        var key11 = "section:section1:key:key1";

        var val00 = Configuration[key00];
        var val01 = Configuration[key01];
        var val10 = Configuration[key10];
        var val11 = Configuration[key11];

        return Content($"{key00} value: {val00} \n" +
                       $"{key01} value: {val01} \n" +
                       $"{key10} value: {val10} \n" +
                       $"{key10} value: {val11} \n"
                       );
    }
}

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

Schlüssel-pro-Datei-Konfigurationsanbieter

KeyPerFileConfigurationProvider verwendet Verzeichnisdateien als Konfigurations-Schlüssel-Wert-Paare. Der Schlüssel ist der Dateiname. Der Wert enthält den 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((hostingContext, config) =>
{
    var path = Path.Combine(
        Directory.GetCurrentDirectory(), "path/to/files");
    config.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:

var builder = WebApplication.CreateBuilder(args);

var Dict = new Dictionary<string, string>
        {
           {"MyKey", "Dictionary MyKey Value"},
           {"Position:Title", "Dictionary_Title"},
           {"Position:Name", "Dictionary_Name" },
           {"Logging:LogLevel:Default", "Warning"}
        };

builder.Host.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.Sources.Clear();

    config.AddInMemoryCollection(Dict);

    config.AddEnvironmentVariables();

    if (args != null)
    {
        config.AddCommandLine(args);
    }
});

builder.Services.AddRazorPages();

var app = builder.Build();

Der folgende Code aus dem Beispieldownload zeigt die vorherigen Konfigurationseinstellungen an:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

Im obigen Code wird config.AddInMemoryCollection(Dict) nach den Standardkonfigurationsanbietern hinzugefügt. Ein Beispiel für das Festlegen der Reihenfolge der Konfigurationsanbieter finden Sie unter JSON-Konfigurationsanbieter.

Ein weiteres Beispiel für die Verwendung von MemoryConfigurationProvider finden Sie unter Binden eines Arrays.

Kestrel-Endpunktkonfiguration

Die Konfiguration des Kestrel-spezifischen Endpunkts überschreibt alle serverübergreifenden Endpunktkonfigurationen. Serverübergreifende Endpunktkonfigurationen umfassen Folgendes:

Beachten Sie die folgende appsettings.json -Datei, die in einer ASP.NET Core-Web-App verwendet wird:

{
  "Kestrel": {
    "Endpoints": {
      "Https": {
        "Url": "https://localhost:9999"
      }
    }
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
} 

Wenn das vorangehende markierte Markup in einer ASP.NET Core-Web-App verwendet und die App in der Befehlszeile mit folgender serverübergreifender Endpunktkonfiguration gestartet wird, gilt Folgendes:

dotnet run --urls="https://localhost:7777"

Kestrel stellt eine Bindung mit dem speziell für Kestrel in der appsettings.json -Datei konfigurierten Endpunkt (https://localhost:9999) und nicht mit https://localhost:7777 her.

Betrachten Sie den speziell für Kestrel konfigurierten Endpunkt als Umgebungsvariable:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

In der vorangehenden Umgebungsvariablen ist Https der Name des Kestrel-spezifischen Endpunkts. Die vorangehende appsettings.json -Datei definiert auch einen Kestrel-spezifischen Endpunkt mit dem Namen Https. Standardmäßig werden Umgebungsvariablen, die den Konfigurationsanbieter für Umgebungsvariablen verwenden, nach appsettings. Environment .json gelesen. Darum wird die vorherige Umgebungsvariable für den Https-Endpunkt verwendet.

GetValue

ConfigurationBinder.GetValue<T> extrahiert einen Einzelwert aus der Konfiguration mit einem angegebenen Schlüssel und konvertiert ihn in den angegebenen Typ:

public class TestNumModel : PageModel
{
    private readonly IConfiguration Configuration;

    public TestNumModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var number = Configuration.GetValue<int>("NumberKey", 99);
        return Content($"{number}");
    }
}

Wenn im obigen Code NumberKey nicht in der Konfiguration gefunden wird, wird der Standardwert 99 verwendet.

GetSection, GetChildren und Exists

Beachten Sie für die nachstehenden Beispiele die folgende Datei MySubsection.json:

{
  "section0": {
    "key0": "value00",
    "key1": "value01"
  },
  "section1": {
    "key0": "value10",
    "key1": "value11"
  },
  "section2": {
    "subsection0": {
      "key0": "value200",
      "key1": "value201"
    },
    "subsection1": {
      "key0": "value210",
      "key1": "value211"
    }
  }
}

Der folgende Code fügt MySubsection.json zu den Konfigurationsanbietern hinzu:

var builder = WebApplication.CreateBuilder(args);

builder.Host.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.AddJsonFile("MySubsection.json",
                       optional: true,
                       reloadOnChange: true);
});

builder.Services.AddRazorPages();

var app = builder.Build();

GetSection

IConfiguration.GetSection gibt einen Konfigurationsunterabschnitt mit dem angegebenen Unterabschnittsschlüssel zurück.

Der folgende Code gibt Werte für section1 zurück:

public class TestSectionModel : PageModel
{
    private readonly IConfiguration Config;

    public TestSectionModel(IConfiguration configuration)
    {
        Config = configuration.GetSection("section1");
    }

    public ContentResult OnGet()
    {
        return Content(
                $"section1:key0: '{Config["key0"]}'\n" +
                $"section1:key1: '{Config["key1"]}'");
    }
}

Der folgende Code gibt Werte für section2:subsection0 zurück:

public class TestSection2Model : PageModel
{
    private readonly IConfiguration Config;

    public TestSection2Model(IConfiguration configuration)
    {
        Config = configuration.GetSection("section2:subsection0");
    }

    public ContentResult OnGet()
    {
        return Content(
                $"section2:subsection0:key0 '{Config["key0"]}'\n" +
                $"section2:subsection0:key1:'{Config["key1"]}'");
    }
}

GetSection gibt nie null zurück. Wenn kein entsprechender Abschnitt gefunden wird, wird ein leeres IConfigurationSection-Element zurückgegeben.

Wenn GetSection einen entsprechenden Abschnitt zurückgibt, wird Value nicht aufgefüllt. Eine Eigenschaft Key und Path werden zurückgegeben, wenn der Abschnitt vorhanden ist.

GetChildren und Exists

Mit dem folgenden Code wird IConfiguration.GetChildren abgerufen, und es werden Werte für section2:subsection0 zurückgegeben:

public class TestSection4Model : PageModel
{
    private readonly IConfiguration Config;

    public TestSection4Model(IConfiguration configuration)
    {
        Config = configuration;
    }

    public ContentResult OnGet()
    {
        string s = "";
        var selection = Config.GetSection("section2");
        if (!selection.Exists())
        {
            throw new Exception("section2 does not exist.");
        }
        var children = selection.GetChildren();

        foreach (var subSection in children)
        {
            int i = 0;
            var key1 = subSection.Key + ":key" + i++.ToString();
            var key2 = subSection.Key + ":key" + i.ToString();
            s += key1 + " value: " + selection[key1] + "\n";
            s += key2 + " value: " + selection[key2] + "\n";
        }
        return Content(s);
    }
}

Der obige Code ruft ConfigurationExtensions.Exists auf, um zu überprüfen, ob der Abschnitt vorhanden ist:

Binden eines Arrays

ConfigurationBinder.Bind unterstützt das Binden von Arrays an Objekte mithilfe von Arrayindizes in Konfigurationsschlüsseln. Jedes Arrayformat, das ein numerisches Schlüsselsegment verfügbar macht, kann ein Array an ein POCO-Klassenarray binden.

Beachten Sie MyArray.json aus dem Beispieldownload:

{
  "array": {
    "entries": {
      "0": "value00",
      "1": "value10",
      "2": "value20",
      "4": "value40",
      "5": "value50"
    }
  }
}

Der folgende Code fügt MyArray.json zu den Konfigurationsanbietern hinzu:

var builder = WebApplication.CreateBuilder(args);

builder.Host.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.AddJsonFile("MyArray.json",
                        optional: true,
                        reloadOnChange: true); ;
});

builder.Services.AddRazorPages();

var app = builder.Build();

Der folgende Code liest die Konfiguration und zeigt die Werte an:

public class ArrayModel : PageModel
{
    private readonly IConfiguration Config;
    public ArrayExample? _array { get; private set; }

    public ArrayModel(IConfiguration config)
    {
        Config = config;
    }

    public ContentResult OnGet()
    {
        if (_array == null)
        {
            throw new ArgumentNullException(nameof(_array));
        }

        _array = Config.GetSection("array").Get<ArrayExample>();
        string s = String.Empty;

        for (int j = 0; j < _array.Entries.Length; j++)
        {
            s += $"Index: {j}  Value:  {_array.Entries[j]} \n";
        }

        return Content(s);
    }
}

Der obige Code erzeugt die folgende Ausgabe:

Index: 0  Value: value00
Index: 1  Value: value10
Index: 2  Value: value20
Index: 3  Value: value40
Index: 4  Value: value50

In der obigen Ausgabe hat Index 3 den Wert value40, der "4": "value40", in MyArray.json entspricht. Die gebundenen Arrayindizes sind kontinuierlich und nicht an den Konfigurationsschlüsselindex gebunden. Der Konfigurationsbinder ist nicht in der Lage, NULL-Werte zu binden oder NULL-Einträge in gebundenen Objekten zu erstellen.

Benutzerdefinierter Konfigurationsanbieter

Die Beispiel-App veranschaulicht, wie ein Standardkonfigurationsanbieter erstellt wird, der Konfigurations-Schlüssel-Wert-Paare aus einer Datenbank mit Entity Framework (EF) liest.

Der Anbieter weist die folgenden Merkmale auf:

  • Die EF-In-Memory-Datenbank wird zu Demonstrationszwecken verwendet. Um eine Datenbank zu verwenden, die eine Verbindungszeichenfolge benötigt, implementieren Sie einen sekundären ConfigurationBuilder, um die Verbindungszeichenfolge aus einem anderen Konfigurationsanbieter anzugeben.
  • Der Anbieter liest eine Datenbanktabelle beim Start in die Konfiguration. Der Anbieter fragt die Datenbank nicht pro Schlüssel ab.
  • Das erneute Laden bei Änderung ist nicht implementiert. Das heißt, das Aktualisieren der Datenbank nach App-Start hat keine Auswirkungen auf die App-Konfiguration.

Definieren Sie eine EFConfigurationValue-Entität zum Speichern von Konfigurationswerten in der Datenbank.

Models/EFConfigurationValue.cs:

public class EFConfigurationValue
{
    public string Id { get; set; } = String.Empty;
    public string Value { get; set; } = String.Empty;
}

Fügen Sie EFConfigurationContext hinzu, um die konfigurierten Werte zu speichern und auf diese zugreifen.

EFConfigurationProvider/EFConfigurationContext.cs:

public class EFConfigurationContext : DbContext
{
    public EFConfigurationContext(DbContextOptions<EFConfigurationContext> options) : base(options)
    {
    }

    public DbSet<EFConfigurationValue> Values => Set<EFConfigurationValue>();
}

Erstellen Sie eine Klasse, die das IConfigurationSource implementiert.

EFConfigurationProvider/EFConfigurationSource.cs:

public class EFConfigurationSource : IConfigurationSource
{
    private readonly Action<DbContextOptionsBuilder> _optionsAction;

    public EFConfigurationSource(Action<DbContextOptionsBuilder> optionsAction) => _optionsAction = optionsAction;

    public IConfigurationProvider Build(IConfigurationBuilder builder) => new EFConfigurationProvider(_optionsAction);
}

Erstellen Sie den benutzerdefinierten Konfigurationsanbieter durch Vererbung von ConfigurationProvider. Der Konfigurationsanbieter initialisiert die Datenbank, wenn diese leer ist. Da für Konfigurationsschlüssel die Groß-/Kleinschreibung nicht relevant ist, wird das zum Initialisieren der Datenbank verwendete Wörterbuch mit der Vergleichsfunktion ohne Beachtung der Groß-/Kleinschreibung erstellt (StringComparer.OrdinalIgnoreCase).

EFConfigurationProvider/EFConfigurationProvider.cs:

public class EFConfigurationProvider : ConfigurationProvider
{
    public EFConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction)
    {
        OptionsAction = optionsAction;
    }

    Action<DbContextOptionsBuilder> OptionsAction { get; }

    public override void Load()
    {
        var builder = new DbContextOptionsBuilder<EFConfigurationContext>();

        OptionsAction(builder);

        using (var dbContext = new EFConfigurationContext(builder.Options))
        {
            if (dbContext == null || dbContext.Values == null)
            {
                throw new Exception("Null DB context");
            }
            dbContext.Database.EnsureCreated();

            Data = !dbContext.Values.Any()
                ? CreateAndSaveDefaultValues(dbContext)
                : dbContext.Values.ToDictionary(c => c.Id, c => c.Value);
        }
    }

    private static IDictionary<string, string> CreateAndSaveDefaultValues(
        EFConfigurationContext dbContext)
    {
        // Quotes (c)2005 Universal Pictures: Serenity
        // https://www.uphe.com/movies/serenity
        var configValues =
            new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
            {
                    { "quote1", "I aim to misbehave." },
                    { "quote2", "I swallowed a bug." },
                    { "quote3", "You can't stop the signal, Mal." }
            };

        if (dbContext == null || dbContext.Values == null)
        {
            throw new Exception("Null DB context");
        }

        dbContext.Values.AddRange(configValues
            .Select(kvp => new EFConfigurationValue
            {
                Id = kvp.Key,
                Value = kvp.Value
            })
            .ToArray());

        dbContext.SaveChanges();

        return configValues;
    }
}

Mit einer AddEFConfiguration-Erweiterungsmethode kann die Konfigurationsquelle ConfigurationBuilder hinzugefügt werden.

Extensions/EntityFrameworkExtensions.cs:

public static class EntityFrameworkExtensions
{
    public static IConfigurationBuilder AddEFConfiguration(
               this IConfigurationBuilder builder,
               Action<DbContextOptionsBuilder> optionsAction)
    {
        return builder.Add(new EFConfigurationSource(optionsAction));
    }
}

Der folgende Code veranschaulicht die Verwendung des benutzerdefinierten Anbieters EFConfigurationProvider in Program.cs:

//using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddEFConfiguration(
    opt => opt.UseInMemoryDatabase("InMemoryDb"));

var app = builder.Build();

app.Run();

Zugriffskonfiguration in Razor Pages

Der folgende Code zeigt Konfigurationsdaten auf einer Razor-Seite an:

@page
@model Test5Model
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

Configuration value for 'MyKey': @Configuration["MyKey"]

Im folgenden Code wird MyOptions mit Configure zum Dienstcontainer hinzugefügt und an die Konfiguration gebunden:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<MyOptions>(
    builder.Configuration.GetSection("MyOptions"));

var app = builder.Build();

Das folgende Markup verwendet die @inject Razor Direktive, um die Optionswerte aufzulösen und anzuzeigen:

@page
@model SampleApp.Pages.Test3Model
@using Microsoft.Extensions.Options
@using SampleApp.Models
@inject IOptions<MyOptions> optionsAccessor


<p><b>Option1:</b> @optionsAccessor.Value.Option1</p>
<p><b>Option2:</b> @optionsAccessor.Value.Option2</p>

Zugriffskonfiguration in einer MVC-Ansichtsdatei

Der folgende Code zeigt Konfigurationsdaten in einer MVC-Ansicht an:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

Configuration value for 'MyKey': @Configuration["MyKey"]

Konfigurieren von Optionen mit einem Delegaten

In einem Delegaten konfigurierte Optionen überschreiben die in den Konfigurationsanbietern festgelegten Werte.

Im folgenden Code wird ein dritter IConfigureOptions<TOptions>-Dienst zum Dienstcontainer hinzugefügt. Er verwendet einen Delegaten, um Werte für MyOptions zu konfigurieren:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<MyOptions>(myOptions =>
{
    myOptions.Option1 = "Value configured in delegate";
    myOptions.Option2 = 500;
});

var app = builder.Build();

Im folgenden Code werden die Optionswerte angezeigt:

public class Test2Model : PageModel
{
    private readonly IOptions<MyOptions> _optionsDelegate;

    public Test2Model(IOptions<MyOptions> optionsDelegate )
    {
        _optionsDelegate = optionsDelegate;
    }

    public ContentResult OnGet()
    {
        return Content($"Option1: {_optionsDelegate.Value.Option1} \n" +
                       $"Option2: {_optionsDelegate.Value.Option2}");
    }
}

Im vorherigen Beispiel wurden die Werte von Option1 und Option2 in appsettings.json angegeben und anschließend vom konfigurierten Delegaten überschrieben.

Hostkonfiguration und App-Konfiguration im Vergleich

Bevor die App konfiguriert und gestartet wird, wird ein Host konfiguriert und gestartet. Der Host ist verantwortlich für das Starten der App und das Verwalten der Lebensdauer. Die App und der Host werden mit den in diesem Thema beschriebenen Konfigurationsanbietern konfiguriert. Schlüssel-Wert-Paare der Hostkonfiguration sind ebenfalls in der globalen App-Konfiguration enthalten. Weitere Informationen dazu, wie Konfigurationsanbieter beim Erstellen des Hosts verwendet werden, und wie sich Konfigurationsquellen auf die Hostkonfiguration auswirken, finden Sie unter ASP.NET Core – Grundlagen.

Standardhostkonfiguration

Ausführliche Informationen zur Standardkonfiguration bei Verwendung des Webhosts finden Sie in der ASP.NET Core 2.2-Version dieses Themas.

  • Die Konfiguration des Hosts wird durch Folgendes festgelegt:
  • Die Webhost-Standardkonfiguration wird eingerichtet (ConfigureWebHostDefaults):
    • Kestrel wird als Webserver verwendet und mithilfe der Konfigurationsanbieter der App konfiguriert.
    • Fügen Sie Middleware zum Filtern von Hosts hinzu.
    • Fügen Sie Middleware für weitergeleitete Header hinzu, wenn die Umgebungsvariable ASPNETCORE_FORWARDEDHEADERS_ENABLED auf true festgelegt ist.
    • Aktivieren Sie die IIS-Integration.

Sonstige Konfiguration

Dieses Thema bezieht sich nur auf App-Konfigurationen. Andere Aspekte des Ausführens und Hostings von ASP.NET Core-Apps werden mithilfe von Konfigurationsdateien konfiguriert, die in diesem Thema nicht behandelt werden:

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

Weitere Informationen zum Migrieren der App-Konfiguration aus früheren Versionen von ASP.NET finden Sie unter Migrieren von ASP.NET zu ASP.NET Core.

Hinzufügen von Konfigurationen aus einer externen Assembly

Eine IHostingStartup-Implementierung ermöglicht das Hinzufügen von Erweiterungen zu einer App beim Start von einer externen Assembly außerhalb der Startup-Klasse der App aus. Weitere Informationen finden Sie unter Verwenden von Hostingstartassemblys in ASP.NET Core.

Zusätzliche Ressourcen

Die Konfiguration in ASP.NET Core erfolgt mithilfe eines oder mehrerer Konfigurationsanbieter. Konfigurationsanbieter lesen Konfigurationsdaten aus Schlüssel-Wert-Paaren unter Verwendung verschiedener Konfigurationsquellen:

  • Einstellungsdateien, z. B. appsettings.json
  • Umgebungsvariablen
  • Azure Key Vault
  • Azure App Configuration
  • Befehlszeilenargumente
  • Benutzerdefinierte Anbieter (installiert oder erstellt)
  • Verzeichnisdateien
  • Speicherinterne .NET Objekte

Dieses Thema enthält Informationen zur Konfiguration in ASP.NET Core. Informationen zur Verwendung der Konfiguration in Konsolen-Apps finden Sie unter .NET-Konfiguration.

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)

Standardkonfiguration

ASP.NET Core-Web-Apps, die mit dotnet new oder Visual Studio erstellt wurden, generieren den folgenden Code:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

CreateDefaultBuilder legt die Standardkonfiguration für die App in der folgenden Reihenfolge fest:

  1. ChainedConfigurationProvider: Fügt eine vorhandene IConfiguration als Quelle hinzu. Im Fall einer Standardkonfiguration wird die Host-Konfiguration hinzugefügt und als erste Quelle für die App- Konfiguration festgelegt.
  2. appsettings.json mithilfe des JSON-Konfigurationsanbieters
  3. appsettings. Environment .json mithilfe des JSON-Konfigurationsanbieters. Beispielsweise appsettings.Production_._json and appsettings.Development _._json.
  4. App-Geheimnisse, wenn die App in der Development-Umgebung ausgeführt wird
  5. Umgebungsvariablen, die den Umgebungsvariablen-Konfigurationsanbieter verwenden
  6. Befehlszeilenargumente, die den Befehlszeilen-Konfigurationsanbieter verwenden

Später hinzugefügte Konfigurationsanbieter überschreiben vorherige Schlüsseleinstellungen. Wenn beispielsweise MyKey sowohl unter appsettings.json als auch unter Umgebung festgelegt wird, wird der Umgebungswert verwendet. Bei Verwendung der Standardkonfigurationsanbieter überschreibt der Befehlszeilen-Konfigurationsanbieter alle anderen Anbieter.

Weitere Informationen zu CreateDefaultBuilder finden Sie unter Standardeinstellungen für den Generator.

Im folgenden Code werden die aktivierten Konfigurationsanbieter in der Reihenfolge angezeigt, in der sie hinzugefügt wurden:

public class Index2Model : PageModel
{
    private IConfigurationRoot ConfigRoot;

    public Index2Model(IConfiguration configRoot)
    {
        ConfigRoot = (IConfigurationRoot)configRoot;
    }

    public ContentResult OnGet()
    {           
        string str = "";
        foreach (var provider in ConfigRoot.Providers.ToList())
        {
            str += provider.ToString() + "\n";
        }

        return Content(str);
    }
}

appsettings.json

Betrachten Sie die folgende appsettings.json -Datei:

{
    "Position": {
        "Title": "Editor",
        "Name": "Joe Smith"
    },
    "MyKey": "My appsettings.json Value",
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        }
    },
    "AllowedHosts": "*"
}

Im folgenden Code aus dem Beispieldownload sind mehrere der vorherigen Konfigurationseinstellungen zu sehen:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

Der Standard-JsonConfigurationProvider lädt die Konfiguration in der folgenden Reihenfolge:

  1. appsettings.json
  2. appsettings. Environment .json: Beispielsweise die Dateien appsettings.Production_._json and appsettings.Development _._json. Die Umgebungsversion der Datei wird basierend auf IHostingEnvironment.EnvironmentName geladen. Weitere Informationen finden Sie unter Verwenden von mehreren Umgebungen in ASP.NET Core.

appsettings.Environment.json-Werte überschreiben Schlüssel in appsettings.json . Standardmäßig sind dies z. B.:

  • In der Entwicklung überschreibt die appsettings.*Development _._json-Konfiguration in appsettings.json gefundene Werte.
  • In der Produktion überschreibt die appsettings.Production _._json-Konfiguration in appsettings.json gefundene Werte. Dies ist beispielsweise bei der Bereitstellung der App in Azure der Fall.

Wenn ein Konfigurationswert garantiert werden muss, nutzen Sie die Informationen unter GetValue. Im vorherigen Beispiel werden nur Zeichenfolgen gelesen, und es wird kein Standardwert unterstützt.

Wenn die Standard-Konfiguration verwendet wird, werden die Dateien appsettings.json und appsettings. Environment .json mit reloadOnChange: true aktiviert. Änderungen an den Dateien appsettings.json und appsettings. Environment .json nach dem Start der App werden vom JSON-Konfigurationsanbieter gelesen.

Binden hierarchischer Konfigurationsdaten mit dem Optionsmuster

Die bevorzugte Methode für das Lesen zugehöriger Konfigurationswerte ist die Verwendung des Optionsmusters. Um z. B. die folgenden Konfigurationswerte zu lesen:

  "Position": {
    "Title": "Editor",
    "Name": "Joe Smith"
  }

Erstellen Sie die folgende neue PositionOptions-Klasse:

public class PositionOptions
{
    public const string Position = "Position";

    public string Title { get; set; }
    public string Name { get; set; }
}

Eine Optionsklasse:

  • Eine Optionsklasse muss nicht abstrakt sein und über einen öffentlichen parameterlosen Konstruktor verfügen.
  • Alle öffentlichen Lese-/Schreibeigenschaften des Typs sind gebunden.
  • Felder werden nicht gebunden. Im vorangehenden Code ist Position nicht gebunden. Die Position-Eigenschaft wird verwendet, sodass die Zeichenfolge "Position" nicht in der App hartcodiert werden muss, wenn die Klasse an einen Konfigurationsanbieter gebunden wird.

Der folgende Code

  • Ruft ConfigurationBinder.Bind auf, um die PositionOptions-Klasse an den Position-Abschnitt zu binden.
  • Zeigt die Position-Konfigurationsdaten an.
public class Test22Model : PageModel
{
    private readonly IConfiguration Configuration;

    public Test22Model(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var positionOptions = new PositionOptions();
        Configuration.GetSection(PositionOptions.Position).Bind(positionOptions);

        return Content($"Title: {positionOptions.Title} \n" +
                       $"Name: {positionOptions.Name}");
    }
}

Im vorangehenden Code werden standardmäßig Änderungen an der JSON-Konfigurationsdatei gelesen, nachdem die App gestartet wurde.

ConfigurationBinder.Get<T> bindet den angegebenen Typ und gibt ihn zurück. ConfigurationBinder.Get<T> ist möglicherweise praktischer als die Verwendung von ConfigurationBinder.Bind. Der folgende Code zeigt die Verwendung von ConfigurationBinder.Get<T> mit der PositionOptions-Klasse:

public class Test21Model : PageModel
{
    private readonly IConfiguration Configuration;
    public PositionOptions positionOptions { get; private set; }

    public Test21Model(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {            
        positionOptions = Configuration.GetSection(PositionOptions.Position)
                                                     .Get<PositionOptions>();

        return Content($"Title: {positionOptions.Title} \n" +
                       $"Name: {positionOptions.Name}");
    }
}

Im vorangehenden Code werden standardmäßig Änderungen an der JSON-Konfigurationsdatei gelesen, nachdem die App gestartet wurde.

Eine alternative Vorgehensweise bei der Verwendung des Optionsmusters besteht darin, den Position-Abschnitt zu binden und ihn zum Dependency-Injection-Dienstcontainer hinzuzufügen. Im folgenden Code wird PositionOptions mit <xref:Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions.Configure_> zum Dienstcontainer hinzugefügt und an die Konfiguration gebunden:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<PositionOptions>(Configuration.GetSection(
                                        PositionOptions.Position));
    services.AddRazorPages();
}

Mithilfe des vorangehenden Codes liest der folgende Code die Positionsoptionen:

public class Test2Model : PageModel
{
    private readonly PositionOptions _options;

    public Test2Model(IOptions<PositionOptions> options)
    {
        _options = options.Value;
    }

    public ContentResult OnGet()
    {
        return Content($"Title: {_options.Title} \n" +
                       $"Name: {_options.Name}");
    }
}

Im vorangehenden Code werden Änderungen an der JSON-Konfigurationsdatei nach dem Start der App nicht gelesen. Verwenden Sie IOptionsSnapshot, um Änderungen lesen zu können, nachdem die App gestartet wurde.

Wenn die Standard-Konfiguration verwendet wird, werden die Dateien appsettings.json und appsettings. Environment .json mit reloadOnChange: true aktiviert. Änderungen an den Dateien appsettings.json und appsettings. Environment .json nach dem Start der App werden vom JSON-Konfigurationsanbieter gelesen.

Weitere Informationen zum Hinzufügen zusätzlicher JSON-Konfigurationsdateien finden Sie unter JSON-Konfigurationsanbieter in diesem Dokument.

Kombinieren von Dienstsammlungen

Mit der folgenden ConfigureServices-Methode können Sie Dienste registrieren und Optionen konfigurieren:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<PositionOptions>(
        Configuration.GetSection(PositionOptions.Position));
    services.Configure<ColorOptions>(
        Configuration.GetSection(ColorOptions.Color));

    services.AddScoped<IMyDependency, MyDependency>();
    services.AddScoped<IMyDependency2, MyDependency2>();

    services.AddRazorPages();
}

Ähnliche Registrierungsgruppen können in eine Erweiterungsmethode verschoben werden, um Dienste zu registrieren. Die Konfigurationsdienste werden beispielsweise folgender Klasse hinzugefügt:

using ConfigSample.Options;
using Microsoft.Extensions.Configuration;

namespace Microsoft.Extensions.DependencyInjection
{
    public static class MyConfigServiceCollectionExtensions
    {
        public static IServiceCollection AddConfig(
             this IServiceCollection services, IConfiguration config)
        {
            services.Configure<PositionOptions>(
                config.GetSection(PositionOptions.Position));
            services.Configure<ColorOptions>(
                config.GetSection(ColorOptions.Color));

            return services;
        }
    }
}

Die verbleibenden Dienste werden in einer ähnlichen Klasse registriert. Die folgende ConfigureServices-Methode verwendet die neuen Erweiterungsmethoden, um die Dienste zu registrieren:

public void ConfigureServices(IServiceCollection services)
{
    services.AddConfig(Configuration)
            .AddMyDependencyGroup();

    services.AddRazorPages();
}

Hinweis: Jede services.Add{GROUP_NAME}-Erweiterungsmethode fügt Dienste hinzu und konfiguriert diese möglicherweise. Beispielsweise fügt AddControllersWithViews den MVC-Controller für Dienste mit den erforderlichen Ansichten hinzu, und AddRazorPages fügt die für Razor Pages benötigten Dienste hinzu. Bei Apps sollte die Namenskonvention zum Erstellen von Erweiterungsmethoden im Microsoft.Extensions.DependencyInjection-Namespace befolgt werden. Erstellen von Erweiterungsmethoden im Microsoft.Extensions.DependencyInjection-Namespace:

  • Kapselt Gruppen von Dienstregistrierungen.
  • Bietet komfortablen IntelliSense-Zugriff auf den Dienst.

Sicherheit und Benutzergeheimnisse

Richtlinien für Konfigurationsdaten:

  • Speichern Sie nie Kennwörter oder andere vertrauliche Daten im Konfigurationsanbietercode oder in Nur-Text-Konfigurationsdateien. Das Secret Manager-Tool kann zum Speichern von Geheimnissen in der Entwicklungsumgebung verwendet werden.
  • Verwenden Sie keine Produktionsgeheimnisse in Entwicklungs- oder Testumgebungen.
  • Geben Sie Geheimnisse außerhalb des Projekts an, damit sie nicht versehentlich in ein Quellcoderepository übernommen werden können.

Im Standardmodell wird die Quelle der Benutzergeheimniskonfiguration nach den Quellen für die JSON-Konfiguration registriert. Daher haben geheime Benutzerschlüssel Vorrang vor Schlüssel in appsettings.json und appsettings. Environment .json.

Weitere Informationen zum Speichern von Kennwörtern oder anderen vertraulichen Daten:

Azure Key Vault speichert App-Geheimnisse für ASP.NET Core-Apps auf sichere Weise. Weitere Informationen finden Sie unter Azure Key Vault-Konfigurationsanbieter in ASP.NET Core.

Umgebungsvariablen

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

Das Trennzeichen : funktioniert nicht auf allen Plattformen mit den hierarchischen Schlüsseln von Umgebungsvariablen. Der doppelte Unterstrich __:

  • wird auf allen Plattformen unterstützt. Das Trennzeichen : wird beispielsweise nicht von Bash unterstützt, __ hingegen schon.
  • automatisch durch : ersetzt.

Die folgenden set-Befehle:

  • Legen die Umgebungsschlüssel und -werte des vorangehenden Beispiels unter Windows fest.
  • Testen die Einstellungen bei Verwendung des Beispieldownloads. Der dotnet run-Befehl muss im Projektverzeichnis ausgeführt werden.
set MyKey="My key from Environment"
set Position__Title=Environment_Editor
set Position__Name=Environment_Rick
dotnet run

Die obigen Umgebungseinstellungen:

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

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 MyKey "My key from setx Environment" /M
setx Position__Title Environment_Editor /M
setx Position__Name Environment_Rick /M

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:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddEnvironmentVariables(prefix: "MyCustomPrefix_");
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Für den Code oben gilt:

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 MyCustomPrefix_MyKey="My key with MyCustomPrefix_ Environment"
set MyCustomPrefix_Position__Title=Editor_with_customPrefix
set MyCustomPrefix_Position__Name=Environment_Rick_cp
dotnet run

Die Standardkonfiguration lädt Umgebungsvariablen und Befehlszeilenargumente, die das Präfix DOTNET_ und ASPNETCORE_ aufweisen. Die Präfixe DOTNET_ und ASPNETCORE_ werden von ASP.NET Core für die Host- und App-Konfiguration, jedoch nicht für die Benutzerkonfiguration verwendet. 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.

Weitere Informationen finden Sie unter Azure-Apps: Überschreiben der App-Konfiguration im Azure-Portal.

Informationen zu Azure-Datenbankverbindungszeichenfolgen finden Sie unter Präfixe für Verbindungszeichenfolgen.

Benennen von Umgebungsvariablen

Umgebungsvariablennamen entsprechen der Struktur einer appsettings.json -Datei. Die Elemente in der Hierarchie werden durch einen doppelten Unterstrich (vorzugsweise) oder einen Doppelpunkt getrennt. Wenn die Elementstruktur ein Array enthält, sollte der Arrayindex als zusätzlicher Elementname in diesem Pfad behandelt werden. Schauen Sie sich die folgende appsettings.json -Datei und ihre entsprechenden Werte an, die als Umgebungsvariablen dargestellt werden.

appsettings.json

{
    "SmtpServer": "smtp.example.com",
    "Logging": [
        {
            "Name": "ToEmail",
            "Level": "Critical",
            "Args": {
                "FromAddress": "MySystem@example.com",
                "ToAddress": "SRE@example.com"
            }
        },
        {
            "Name": "ToConsole",
            "Level": "Information"
        }
    ]
}

Umgebungsvariablen

setx SmtpServer=smtp.example.com
setx Logging__0__Name=ToEmail
setx Logging__0__Level=Critical
setx Logging__0__Args__FromAddress=MySystem@example.com
setx Logging__0__Args__ToAddress=SRE@example.com
setx Logging__1__Name=ToConsole
setx Logging__1__Level=Information

In generierter Datei „launchSettings.json“ festgelegte Umgebungsvariablen

Umgebungsvariablen, die in der Datei launchSettings.json festgelegt sind, überschreiben diejenigen, die in der Systemumgebung festgelegt sind. Die ASP.NET Core-Webvorlagen generieren z. B. eine launchSettings.json-Datei, mit der die Endpunktkonfiguration auf Folgendes festgelegt wird:

"applicationUrl": "https://localhost:5001;http://localhost:5000"

Beim Konfigurieren der applicationUrl wird die ASPNETCORE_URLS-Umgebungsvariable festgelegt, und die in der Umgebung festgelegten Werte werden überschrieben.

Umgebungsvariablen unter Linux mit einem Escapezeichen versehen

Unter Linux muss der Wert von URL-Umgebungsvariablen mit einem Escapezeichen versehen werden, damit systemd ihn analysieren kann. Verwenden Sie das Linux-Tool systemd-escape, das http:--localhost:5001 erzeugt.

groot@terminus:~$ systemd-escape http://localhost:5001
http:--localhost:5001

Anzeigen von Umgebungsvariablen

Der folgende Code zeigt die Umgebungsvariablen und Werte beim Anwendungsstart an, was beim Debuggen von Umgebungseinstellungen hilfreich sein kann:

public static void Main(string[] args)
{
    var host = CreateHostBuilder(args).Build();

    var config = host.Services.GetRequiredService<IConfiguration>();

    foreach (var c in config.AsEnumerable())
    {
        Console.WriteLine(c.Key + " = " + c.Value);
    }
    host.Run();
}

Befehlszeile

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

  • In den Dateien appsettings.json und appsettings.Environment.json
  • App-Geheimnisse in der Entwicklungsumgebung.
  • Umgebungsvariablen.

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

Befehlszeilenargumente

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

dotnet run MyKey="My key from command line" Position:Title=Cmd Position:Name=Cmd_Rick

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

dotnet run /MyKey "Using /" /Position:Title=Cmd_ /Position:Name=Cmd_Rick

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

dotnet run --MyKey "Using --" --Position:Title=Cmd-- --Position:Name=Cmd--Rick

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 MySetting=.

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

Switchmappings

Switchmappings erlauben das Angeben einer Logik zum Ersetzen von Schlüsselnamen. Stellen Sie ein Wörterbuch mit Switchersetzungen für die AddCommandLine-Methode bereit.

Wenn das Switchmappingwörterbuch verwendet wird, wird das Wörterbuch für Schlüssel, die dem von einem Befehlszeilenargument angegebenen Schlüssel entsprechen, überprüft. Wenn der Befehlszeilenschlüssel im Wörterbuch gefunden wird, wird der Wörterbuchwert zum Festlegen des Schlüssel-Wert-Paares in der App-Konfiguration zurückgegeben. Ein Switchmapping ist für jeden Befehlszeilenschlüssel erforderlich, dem ein einzelner Gedankenstrich (-) vorangestellt ist.

Regeln für Schlüssel von Switchmappingwörterbüchern:

  • Switches müssen mit - oder -- beginnen.
  • Das Switchmappingwörterbuch darf keine doppelten Schlüssel enthalten.

Wenn Sie ein Switchmappingwörterbuch verwenden möchten, übergeben Sie es an den AddCommandLine-Abruf:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var switchMappings = new Dictionary<string, string>()
         {
             { "-k1", "key1" },
             { "-k2", "key2" },
             { "--alt3", "key3" },
             { "--alt4", "key4" },
             { "--alt5", "key5" },
             { "--alt6", "key6" },
         };

        return Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddCommandLine(args, switchMappings);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
    }
}

Der folgende Code zeigt die Schlüsselwerte für die ersetzten Schlüssel:

public class Test3Model : PageModel
{
    private readonly IConfiguration Config;

    public Test3Model(IConfiguration configuration)
    {
        Config = configuration;
    }

    public ContentResult OnGet()
    {
        return Content(
                $"Key1: '{Config["Key1"]}'\n" +
                $"Key2: '{Config["Key2"]}'\n" +
                $"Key3: '{Config["Key3"]}'\n" +
                $"Key4: '{Config["Key4"]}'\n" +
                $"Key5: '{Config["Key5"]}'\n" +
                $"Key6: '{Config["Key6"]}'");
    }
}

Mit dem folgenden Befehl kann die Schlüsselersetzung getestet werden:

dotnet run -k1 value1 -k2 value2 --alt3=value2 /alt4=value3 --alt5 value5 /alt6 value6

Bei Apps, die Switchmappings verwenden, sollten im CreateDefaultBuilder-Aufruf keine Argumente übergeben werden. Der AddCommandLine-Aufruf der CreateDefaultBuilder-Methode umfasst keine zugeordneten Switches, und das Switchmappingwörterbuch kann nicht an CreateDefaultBuilder übergeben werden. Die Lösung besteht nicht darin, die Argumente an CreateDefaultBuilder zu übergeben, sondern der AddCommandLine-Methode der ConfigurationBuilder-Methode zu erlauben, sowohl die Argumente als auch das Switchmappingwörterbuch zu verarbeiten.

Festlegen von Umgebungs- und Befehlszeilenargumenten mit Visual Studio

Die folgende Abbildung veranschaulicht das Festlegen von Umgebungs- und Befehlszeilenargumenten mit Visual Studio:

Registerkarte "Debuggen" von VS

In Visual Studio 2019 Version 16.10 Preview 4 und höher werden Umgebungs- und Befehlszeilenargumente über die Benutzeroberfläche für Startprofile festgelegt:

Benutzeroberfläche für Startprofile

Hierarchische Konfigurationsdaten

Die Konfigurations-API liest hierarchische Konfigurationsdaten, indem sie die hierarchischen Daten mit einem Trennzeichen in den Konfigurationsschlüsseln vereinfacht.

Der Beispieldownload enthält die folgende Datei appsettings.json :

{
    "Position": {
        "Title": "Editor",
        "Name": "Joe Smith"
    },
    "MyKey": "My appsettings.json Value",
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        }
    },
    "AllowedHosts": "*"
}

Der folgende Code aus dem Beispieldownload zeigt einige der Konfigurationseinstellungen:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

Die bevorzugte Methode zum Lesen hierarchischer Konfigurationsdaten ist die Verwendung des Optionsmusters. Weitere Informationen finden Sie unter Binden hierarchischer Konfigurationsdaten in diesem Dokument.

Mit den Methoden GetSection und GetChildren können Abschnitte und untergeordnete Abschnittelemente in den Konfigurationsdaten isoliert werden. Diese Methoden werden später im Abschnitt GetSection, GetChildren und Exists beschrieben.

Konfigurationsschlüssel und -werte

Konfigurationsschlüssel:

  • Die Groß-/Kleinschreibung wird nicht berücksichtigt. Beispielsweise verweisen ConnectionString und connectionstring auf denselben Schlüssel.
  • Wenn ein Schlüssel und ein Wert in mehreren Konfigurationsanbietern festgelegt ist, wird der Wert des zuletzt hinzugefügten Anbieters verwendet. Weitere Informationen finden Sie unter Standardkonfiguration.
  • Hierarchische Schlüssel
    • Innerhalb der Konfigurations-API funktioniert ein Doppelpunkt (:) als Trennzeichen auf allen Plattformen.
    • In Umgebungsvariablen funktioniert ein Doppelpunkt als Trennzeichen ggf. nicht auf allen Plattformen. Ein doppelter Unterstrich (__) wird von allen Plattformen unterstützt und automatisch in einen Doppelpunkt (:) umgewandelt.
    • In Azure Key Vault verwenden hierarchische Schlüssel -- als Trennzeichen. Der Azure Key Vault-Konfigurationsanbieter ersetzt -- automatisch durch :, wenn die Geheimnisse in die Konfiguration der App geladen werden.
  • ConfigurationBinder unterstützt das Binden von Arrays an Objekte mit Arrayindizes in Konfigurationsschlüsseln. Die Arraybindung wird im Abschnitt Binden eines Arrays an eine Klasse beschrieben.

Konfigurationswerte:

  • Sind Zeichenfolgen.
  • NULL-Werte können nicht in einer Konfiguration gespeichert oder an Objekte gebunden werden.

Konfigurationsanbieter

Die folgende Tabelle zeigt die für ASP.NET Core-Apps verfügbaren Konfigurationsanbieter.

Anbieter Bereitstellung der Konfiguration über
Azure Key Vault-Konfigurationsanbieter Azure Key Vault
Azure-App-Konfigurationsanbieter Azure App Configuration
Befehlszeilen-Konfigurationsanbieter Befehlszeilenparameter
Benutzerdefinierter Konfigurationsanbieter Benutzerdefinierte Quelle
Umgebungsvariablen-Konfigurationsanbieter Umgebungsvariablen
Dateikonfigurationsanbieter INI-, JSON- und XML-Dateien
Schlüssel-pro-Datei-Konfigurationsanbieter Verzeichnisdateien
Speicherkonfigurationsanbieter In-Memory-Sammlungen
Benutzergeheimnisse Datei im Benutzerprofilverzeichnis

Konfigurationsquellen werden in der Reihenfolge gelesen, in der ihre Konfigurationsanbieter angegeben sind. Ordnen Sie die Konfigurationsanbieter im Code so an, dass sie den Prioritäten für die zugrunde liegenden Konfigurationsquellen entsprechen, die für die App erforderlich sind.

Eine typische Konfigurationsanbietersequenz ist:

  1. appsettings.json
  2. appsettings.Environment.json
  3. Benutzergeheimnisse
  4. Umgebungsvariablen, die den Umgebungsvariablen-Konfigurationsanbieter verwenden
  5. Befehlszeilenargumente, die den Befehlszeilen-Konfigurationsanbieter verwenden

In der Regel werden Befehlszeilen-Konfigurationsanbieter in einer Reihe von Anbietern an letzter Stelle hinzugefügt, damit Befehlszeilenargumente die von anderen Anbietern festgelegte Konfiguration überschreiben können.

Die obige Sequenz von Anbietern wird in der Standardkonfiguration verwendet.

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

Dateikonfigurationsanbieter

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

INI-Konfigurationsanbieter

IniConfigurationProvider lädt während der Laufzeit die Konfiguration aus den Schlüssel-Wert-Paaren der INI-Datei.

Mit dem folgenden Code werden alle Konfigurationsanbieter gelöscht und mehrere Konfigurationsanbieter hinzugefügt:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

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

                var env = hostingContext.HostingEnvironment;

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

                config.AddEnvironmentVariables();

                if (args != null)
                {
                    config.AddCommandLine(args);
                }
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Im obigen Code werden Einstellungen in den Dateien MyIniConfig.ini und MyIniConfig.Environment.ini überschrieben durch Einstellungen im:

Der Beispieldownload enthält die folgende Datei MyIniConfig.ini:

MyKey="MyIniConfig.ini Value"

[Position]
Title="My INI Config title"
Name="My INI Config name"

[Logging:LogLevel]
Default=Information
Microsoft=Warning

Im folgenden Code aus dem Beispieldownload sind mehrere der vorherigen Konfigurationseinstellungen zu sehen:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

JSON-Konfigurationsanbieter

Der JsonConfigurationProvider lädt die Konfiguration aus den Schlüssel-Wert-Paaren der JSON-Datei.

Überladungen können Folgendes angeben:

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

Betrachten Sie folgenden Code:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddJsonFile("MyConfig.json", 
                    optional: true, 
                    reloadOnChange: true);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Der vorangehende Code:

In der Regel möchten Sie nicht, dass eine benutzerdefinierte JSON-Datei Werte überschreibt, die im Umgebungsvariablen-Konfigurationsanbieter und im Befehlszeilen-Konfigurationsanbieter festgelegt sind.

Mit dem folgenden Code werden alle Konfigurationsanbieter gelöscht und mehrere Konfigurationsanbieter hinzugefügt:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

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

                var env = hostingContext.HostingEnvironment;

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

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

                config.AddEnvironmentVariables();

                if (args != null)
                {
                    config.AddCommandLine(args);
                }
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Im obigen Code gilt für Einstellungen in den Dateien MyConfig.json und MyConfig.Environment.json:

Der Beispieldownload enthält die folgende Datei MyConfig.json:

{
    "Position": {
        "Title": "Eigener Konfigurationstitel",
        "Name": "My Config Smith"
    },
    "MyKey": "MyConfig.json Value",
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        }
    },
    "AllowedHosts": "*"
}

Im folgenden Code aus dem Beispieldownload sind mehrere der vorherigen Konfigurationseinstellungen zu sehen:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

XML-Konfigurationsanbieter

XmlConfigurationProvider lädt während der Laufzeit die Konfiguration aus den Schlüssel-Wert-Paaren der XML-Datei.

Mit dem folgenden Code werden alle Konfigurationsanbieter gelöscht und mehrere Konfigurationsanbieter hinzugefügt:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

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

                var env = hostingContext.HostingEnvironment;

                config.AddXmlFile("MyXMLFile.xml", optional: true, reloadOnChange: true)
                      .AddXmlFile($"MyXMLFile.{env.EnvironmentName}.xml",
                                     optional: true, reloadOnChange: true);

                config.AddEnvironmentVariables();

                if (args != null)
                {
                    config.AddCommandLine(args);
                }
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Im obigen Code werden Einstellungen in den Dateien MyXMLFile.xml und MyXMLFile.Environment.xml überschrieben durch Einstellungen im:

Der Beispieldownload enthält die folgende Datei MyXMLFile.xml:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <MyKey>MyXMLFile Value</MyKey>
  <Position>
    <Title>Title from  MyXMLFile</Title>
    <Name>Name from MyXMLFile</Name>
  </Position>
  <Logging>
    <LogLevel>
      <Default>Information</Default>
      <Microsoft>Warning</Microsoft>
    </LogLevel>
  </Logging>
</configuration>

Im folgenden Code aus dem Beispieldownload sind mehrere der vorherigen Konfigurationseinstellungen zu sehen:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

Wiederholte Elemente mit den gleichen Elementnamen funktionieren, wenn das name-Attribut zur Unterscheidung der Elemente verwendet wird:

<?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:

public class IndexModel : PageModel
{
    private readonly IConfiguration Configuration;

    public IndexModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var key00 = "section:section0:key:key0";
        var key01 = "section:section0:key:key1";
        var key10 = "section:section1:key:key0";
        var key11 = "section:section1:key:key1";

        var val00 = Configuration[key00];
        var val01 = Configuration[key01];
        var val10 = Configuration[key10];
        var val11 = Configuration[key11];

        return Content($"{key00} value: {val00} \n" +
                       $"{key01} value: {val01} \n" +
                       $"{key10} value: {val10} \n" +
                       $"{key10} value: {val11} \n"
                       );
    }
}

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

Schlüssel-pro-Datei-Konfigurationsanbieter

KeyPerFileConfigurationProvider verwendet Verzeichnisdateien als Konfigurations-Schlüssel-Wert-Paare. Der Schlüssel ist der Dateiname. Der Wert enthält den 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((hostingContext, config) =>
{
    var path = Path.Combine(
        Directory.GetCurrentDirectory(), "path/to/files");
    config.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:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var Dict = new Dictionary<string, string>
        {
           {"MyKey", "Dictionary MyKey Value"},
           {"Position:Title", "Dictionary_Title"},
           {"Position:Name", "Dictionary_Name" },
           {"Logging:LogLevel:Default", "Warning"}
        };

        return Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddInMemoryCollection(Dict);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
    }
}

Der folgende Code aus dem Beispieldownload zeigt die vorherigen Konfigurationseinstellungen an:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

Im obigen Code wird config.AddInMemoryCollection(Dict) nach den Standardkonfigurationsanbietern hinzugefügt. Ein Beispiel für das Festlegen der Reihenfolge der Konfigurationsanbieter finden Sie unter JSON-Konfigurationsanbieter.

Ein weiteres Beispiel für die Verwendung von MemoryConfigurationProvider finden Sie unter Binden eines Arrays.

Kestrel-Endpunktkonfiguration

Die Konfiguration des Kestrel-spezifischen Endpunkts überschreibt alle serverübergreifenden Endpunktkonfigurationen. Serverübergreifende Endpunktkonfigurationen umfassen Folgendes:

Beachten Sie die folgende appsettings.json -Datei, die in einer ASP.NET Core-Web-App verwendet wird:

{
  "Kestrel": {
    "Endpoints": {
      "Https": {
        "Url": "https://localhost:9999"
      }
    }
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
} 

Wenn das vorangehende markierte Markup in einer ASP.NET Core-Web-App verwendet und die App in der Befehlszeile mit folgender serverübergreifender Endpunktkonfiguration gestartet wird, gilt Folgendes:

dotnet run --urls="https://localhost:7777"

Kestrel stellt eine Bindung mit dem speziell für Kestrel in der appsettings.json -Datei konfigurierten Endpunkt (https://localhost:9999) und nicht mit https://localhost:7777 her.

Betrachten Sie den speziell für Kestrel konfigurierten Endpunkt als Umgebungsvariable:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

In der vorangehenden Umgebungsvariablen ist Https der Name des Kestrel-spezifischen Endpunkts. Die vorangehende appsettings.json -Datei definiert auch einen Kestrel-spezifischen Endpunkt mit dem Namen Https. Standardmäßig werden Umgebungsvariablen, die den Konfigurationsanbieter für Umgebungsvariablen verwenden, nach appsettings. Environment .json gelesen. Darum wird die vorherige Umgebungsvariable für den Https-Endpunkt verwendet.

GetValue

ConfigurationBinder.GetValue<T> extrahiert einen Einzelwert aus der Konfiguration mit einem angegebenen Schlüssel und konvertiert ihn in den angegebenen Typ:

public class TestNumModel : PageModel
{
    private readonly IConfiguration Configuration;

    public TestNumModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var number = Configuration.GetValue<int>("NumberKey", 99);
        return Content($"{number}");
    }
}

Wenn im obigen Code NumberKey nicht in der Konfiguration gefunden wird, wird der Standardwert 99 verwendet.

GetSection, GetChildren und Exists

Beachten Sie für die nachstehenden Beispiele die folgende Datei MySubsection.json:

{
  "section0": {
    "key0": "value00",
    "key1": "value01"
  },
  "section1": {
    "key0": "value10",
    "key1": "value11"
  },
  "section2": {
    "subsection0": {
      "key0": "value200",
      "key1": "value201"
    },
    "subsection1": {
      "key0": "value210",
      "key1": "value211"
    }
  }
}

Der folgende Code fügt MySubsection.json zu den Konfigurationsanbietern hinzu:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddJsonFile("MySubsection.json", 
                    optional: true, 
                    reloadOnChange: true);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

GetSection

IConfiguration.GetSection gibt einen Konfigurationsunterabschnitt mit dem angegebenen Unterabschnittsschlüssel zurück.

Der folgende Code gibt Werte für section1 zurück:

public class TestSectionModel : PageModel
{
    private readonly IConfiguration Config;

    public TestSectionModel(IConfiguration configuration)
    {
        Config = configuration.GetSection("section1");
    }

    public ContentResult OnGet()
    {
        return Content(
                $"section1:key0: '{Config["key0"]}'\n" +
                $"section1:key1: '{Config["key1"]}'");
    }
}

Der folgende Code gibt Werte für section2:subsection0 zurück:

public class TestSection2Model : PageModel
{
    private readonly IConfiguration Config;

    public TestSection2Model(IConfiguration configuration)
    {
        Config = configuration.GetSection("section2:subsection0");
    }

    public ContentResult OnGet()
    {
        return Content(
                $"section2:subsection0:key0 '{Config["key0"]}'\n" +
                $"section2:subsection0:key1:'{Config["key1"]}'");
    }
}

GetSection gibt nie null zurück. Wenn kein entsprechender Abschnitt gefunden wird, wird ein leeres IConfigurationSection-Element zurückgegeben.

Wenn GetSection einen entsprechenden Abschnitt zurückgibt, wird Value nicht aufgefüllt. Eine Eigenschaft Key und Path werden zurückgegeben, wenn der Abschnitt vorhanden ist.

GetChildren und Exists

Mit dem folgenden Code wird IConfiguration.GetChildren abgerufen, und es werden Werte für section2:subsection0 zurückgegeben:

public class TestSection4Model : PageModel
{
    private readonly IConfiguration Config;

    public TestSection4Model(IConfiguration configuration)
    {
        Config = configuration;
    }

    public ContentResult OnGet()
    {
        string s = null;
        var selection = Config.GetSection("section2");
        if (!selection.Exists())
        {
            throw new System.Exception("section2 does not exist.");
        }
        var children = selection.GetChildren();

        foreach (var subSection in children)
        {
            int i = 0;
            var key1 = subSection.Key + ":key" + i++.ToString();
            var key2 = subSection.Key + ":key" + i.ToString();
            s += key1 + " value: " + selection[key1] + "\n";
            s += key2 + " value: " + selection[key2] + "\n";
        }
        return Content(s);
    }
}

Der obige Code ruft ConfigurationExtensions.Exists auf, um zu überprüfen, ob der Abschnitt vorhanden ist:

Binden eines Arrays

ConfigurationBinder.Bind unterstützt das Binden von Arrays an Objekte mithilfe von Arrayindizes in Konfigurationsschlüsseln. Jedes Arrayformat, das ein numerisches Schlüsselsegment verfügbar macht, kann ein Array an ein POCO-Klassenarray binden.

Beachten Sie MyArray.json aus dem Beispieldownload:

{
  "array": {
    "entries": {
      "0": "value00",
      "1": "value10",
      "2": "value20",
      "4": "value40",
      "5": "value50"
    }
  }
}

Der folgende Code fügt MyArray.json zu den Konfigurationsanbietern hinzu:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddJsonFile("MyArray.json", 
                    optional: true, 
                    reloadOnChange: true);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Der folgende Code liest die Konfiguration und zeigt die Werte an:

public class ArrayModel : PageModel
{
    private readonly IConfiguration Config;
    public ArrayExample _array { get; private set; }

    public ArrayModel(IConfiguration config)
    {
        Config = config;
    }

    public ContentResult OnGet()
    {
        _array = Config.GetSection("array").Get<ArrayExample>();
        string s = null;

        for (int j = 0; j < _array.Entries.Length; j++)
        {
            s += $"Index: {j}  Value:  {_array.Entries[j]} \n";
        }

        return Content(s);
    }
}

Der obige Code erzeugt die folgende Ausgabe:

Index: 0  Value: value00
Index: 1  Value: value10
Index: 2  Value: value20
Index: 3  Value: value40
Index: 4  Value: value50

In der obigen Ausgabe hat Index 3 den Wert value40, der "4": "value40", in MyArray.json entspricht. Die gebundenen Arrayindizes sind kontinuierlich und nicht an den Konfigurationsschlüsselindex gebunden. Der Konfigurationsbinder ist nicht in der Lage, NULL-Werte zu binden oder NULL-Einträge in gebundenen Objekten zu erstellen.

Mit dem folgenden Code wird die array:entries-Konfiguration mit der AddInMemoryCollection-Erweiterungsmethode geladen:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var arrayDict = new Dictionary<string, string>
        {
            {"array:entries:0", "value0"},
            {"array:entries:1", "value1"},
            {"array:entries:2", "value2"},
            //              3   Skipped
            {"array:entries:4", "value4"},
            {"array:entries:5", "value5"}
        };

        return Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddInMemoryCollection(arrayDict);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
    }
}

Der folgende Code liest die Konfiguration im arrayDict Dictionary und zeigt die Werte an:

public class ArrayModel : PageModel
{
    private readonly IConfiguration Config;
    public ArrayExample _array { get; private set; }

    public ArrayModel(IConfiguration config)
    {
        Config = config;
    }

    public ContentResult OnGet()
    {
        _array = Config.GetSection("array").Get<ArrayExample>();
        string s = null;

        for (int j = 0; j < _array.Entries.Length; j++)
        {
            s += $"Index: {j}  Value:  {_array.Entries[j]} \n";
        }

        return Content(s);
    }
}

Der obige Code erzeugt die folgende Ausgabe:

Index: 0  Value: value0
Index: 1  Value: value1
Index: 2  Value: value2
Index: 3  Value: value4
Index: 4  Value: value5

Index #3 im gebundenen Objekt enthält die Konfigurationsdaten für den array:4-Konfigurationsschlüssel und die Wert für value4. Beim Binden von Konfigurationsdaten, die ein Array enthalten, werden die Arrayindizes in den Konfigurationsschlüsseln zum Durchlaufen der Konfigurationsdaten beim Erstellen des Objekts verwendet. Ein NULL-Wert kann in den Konfigurationsdaten nicht beibehalten werden, und ein NULL-Eintrag wird nicht in einem gebundenen Objekt erstellt, wenn ein Array in Konfigurationsschlüsseln mindestens einen Index überspringt.

Das fehlende Konfigurationselement für Index #3 kann vor dem Binden an die ArrayExample-Instanz von jedem Konfigurationsanbieter bereitgestellt werden, der das Schlüssel-Wert-Paar von Index #3 liest. Beachten Sie die folgende Datei Value3.json aus dem Beispieldownload:

{
  "array:entries:3": "value3"
}

Der folgende Code enthält die Konfiguration für Value3.json und das arrayDict Dictionary:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var arrayDict = new Dictionary<string, string>
        {
            {"array:entries:0", "value0"},
            {"array:entries:1", "value1"},
            {"array:entries:2", "value2"},
            //              3   Skipped
            {"array:entries:4", "value4"},
            {"array:entries:5", "value5"}
        };

        return Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddInMemoryCollection(arrayDict);
                config.AddJsonFile("Value3.json",
                                    optional: false, reloadOnChange: false);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
    }
}

Der folgende Code liest die obige Konfiguration und zeigt die Werte an:

public class ArrayModel : PageModel
{
    private readonly IConfiguration Config;
    public ArrayExample _array { get; private set; }

    public ArrayModel(IConfiguration config)
    {
        Config = config;
    }

    public ContentResult OnGet()
    {
        _array = Config.GetSection("array").Get<ArrayExample>();
        string s = null;

        for (int j = 0; j < _array.Entries.Length; j++)
        {
            s += $"Index: {j}  Value:  {_array.Entries[j]} \n";
        }

        return Content(s);
    }
}

Der obige Code erzeugt die folgende Ausgabe:

Index: 0  Value: value0
Index: 1  Value: value1
Index: 2  Value: value2
Index: 3  Value: value3
Index: 4  Value: value4
Index: 5  Value: value5

Benutzerdefinierte Konfigurationsanbieter sind nicht erforderlich, um Arraybindung zu implementieren.

Benutzerdefinierter Konfigurationsanbieter

Die Beispiel-App veranschaulicht, wie ein Standardkonfigurationsanbieter erstellt wird, der Konfigurations-Schlüssel-Wert-Paare aus einer Datenbank mit Entity Framework (EF) liest.

Der Anbieter weist die folgenden Merkmale auf:

  • Die EF-In-Memory-Datenbank wird zu Demonstrationszwecken verwendet. Um eine Datenbank zu verwenden, die eine Verbindungszeichenfolge benötigt, implementieren Sie einen sekundären ConfigurationBuilder, um die Verbindungszeichenfolge aus einem anderen Konfigurationsanbieter anzugeben.
  • Der Anbieter liest eine Datenbanktabelle beim Start in die Konfiguration. Der Anbieter fragt die Datenbank nicht pro Schlüssel ab.
  • Das erneute Laden bei Änderung ist nicht implementiert. Das heißt, das Aktualisieren der Datenbank nach App-Start hat keine Auswirkungen auf die App-Konfiguration.

Definieren Sie eine EFConfigurationValue-Entität zum Speichern von Konfigurationswerten in der Datenbank.

Models/EFConfigurationValue.cs:

public class EFConfigurationValue
{
    public string Id { get; set; }
    public string Value { get; set; }
}

Fügen Sie EFConfigurationContext hinzu, um die konfigurierten Werte zu speichern und auf diese zugreifen.

EFConfigurationProvider/EFConfigurationContext.cs:

// using Microsoft.EntityFrameworkCore;

public class EFConfigurationContext : DbContext
{
    public EFConfigurationContext(DbContextOptions options) : base(options)
    {
    }

    public DbSet<EFConfigurationValue> Values { get; set; }
}

Erstellen Sie eine Klasse, die das IConfigurationSource implementiert.

EFConfigurationProvider/EFConfigurationSource.cs:

// using Microsoft.EntityFrameworkCore;
// using Microsoft.Extensions.Configuration;

public class EFConfigurationSource : IConfigurationSource
{
    private readonly Action<DbContextOptionsBuilder> _optionsAction;

    public EFConfigurationSource(Action<DbContextOptionsBuilder> optionsAction)
    {
        _optionsAction = optionsAction;
    }

    public IConfigurationProvider Build(IConfigurationBuilder builder)
    {
        return new EFConfigurationProvider(_optionsAction);
    }
}

Erstellen Sie den benutzerdefinierten Konfigurationsanbieter durch Vererbung von ConfigurationProvider. Der Konfigurationsanbieter initialisiert die Datenbank, wenn diese leer ist. Da für Konfigurationsschlüssel die Groß-/Kleinschreibung nicht relevant ist, wird das zum Initialisieren der Datenbank verwendete Wörterbuch mit der Vergleichsfunktion ohne Beachtung der Groß-/Kleinschreibung erstellt (StringComparer.OrdinalIgnoreCase).

EFConfigurationProvider/EFConfigurationProvider.cs:

// using Microsoft.EntityFrameworkCore;
// using Microsoft.Extensions.Configuration;

public class EFConfigurationProvider : ConfigurationProvider
{
    public EFConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction)
    {
        OptionsAction = optionsAction;
    }

    Action<DbContextOptionsBuilder> OptionsAction { get; }

    public override void Load()
    {
        var builder = new DbContextOptionsBuilder<EFConfigurationContext>();

        OptionsAction(builder);

        using (var dbContext = new EFConfigurationContext(builder.Options))
        {
            dbContext.Database.EnsureCreated();

            Data = !dbContext.Values.Any()
                ? CreateAndSaveDefaultValues(dbContext)
                : dbContext.Values.ToDictionary(c => c.Id, c => c.Value);
        }
    }

    private static IDictionary<string, string> CreateAndSaveDefaultValues(
        EFConfigurationContext dbContext)
    {
        // Quotes (c)2005 Universal Pictures: Serenity
        // https://www.uphe.com/movies/serenity
        var configValues = 
            new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
            {
                { "quote1", "I aim to misbehave." },
                { "quote2", "I swallowed a bug." },
                { "quote3", "You can't stop the signal, Mal." }
            };

        dbContext.Values.AddRange(configValues
            .Select(kvp => new EFConfigurationValue 
                {
                    Id = kvp.Key,
                    Value = kvp.Value
                })
            .ToArray());

        dbContext.SaveChanges();

        return configValues;
    }
}

Mit einer AddEFConfiguration-Erweiterungsmethode kann die Konfigurationsquelle ConfigurationBuilder hinzugefügt werden.

Extensions/EntityFrameworkExtensions.cs:

// using Microsoft.EntityFrameworkCore;
// using Microsoft.Extensions.Configuration;

public static class EntityFrameworkExtensions
{
    public static IConfigurationBuilder AddEFConfiguration(
        this IConfigurationBuilder builder, 
        Action<DbContextOptionsBuilder> optionsAction)
    {
        return builder.Add(new EFConfigurationSource(optionsAction));
    }
}

Der folgende Code veranschaulicht die Verwendung des benutzerdefinierten Anbieters EFConfigurationProvider in Program.cs:

// using Microsoft.EntityFrameworkCore;

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            config.AddEFConfiguration(
                options => options.UseInMemoryDatabase("InMemoryDb"));
        })

Zugriffskonfiguration beim Start

Der folgende Code zeigt Konfigurationsdaten in Startup-Methoden an:

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

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
        Console.WriteLine($"MyKey : {Configuration["MyKey"]}");
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        Console.WriteLine($"Position:Title : {Configuration["Position:Title"]}");

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
        });
    }
}

Ein Beispiel für den Zugriff auf die Konfiguration mit den Starthilfsmethoden finden Sie unter Anwendungsstart: Hilfsmethoden.

Zugriffskonfiguration in Razor Pages

Der folgende Code zeigt Konfigurationsdaten auf einer Razor-Seite an:

@page
@model Test5Model
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

Configuration value for 'MyKey': @Configuration["MyKey"]

Im folgenden Code wird MyOptions mit Configure zum Dienstcontainer hinzugefügt und an die Konfiguration gebunden:

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

    services.AddRazorPages();
}

Das folgende Markup verwendet die @inject Razor Direktive, um die Optionswerte aufzulösen und anzuzeigen:

@page
@model SampleApp.Pages.Test3Model
@using Microsoft.Extensions.Options
@inject IOptions<MyOptions> optionsAccessor


<p><b>Option1:</b> @optionsAccessor.Value.Option1</p>
<p><b>Option2:</b> @optionsAccessor.Value.Option2</p>

Zugriffskonfiguration in einer MVC-Ansichtsdatei

Der folgende Code zeigt Konfigurationsdaten in einer MVC-Ansicht an:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

Configuration value for 'MyKey': @Configuration["MyKey"]

Konfigurieren von Optionen mit einem Delegaten

In einem Delegaten konfigurierte Optionen überschreiben die in den Konfigurationsanbietern festgelegten Werte.

Das Konfigurieren von Optionen mit einem Delegaten wird als Beispiel 2 in der Beispiel-App veranschaulicht.

Im folgenden Code wird ein dritter IConfigureOptions<TOptions>-Dienst zum Dienstcontainer hinzugefügt. Er verwendet einen Delegaten, um Werte für MyOptions zu konfigurieren:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<MyOptions>(myOptions =>
    {
        myOptions.Option1 = "Value configured in delegate";
        myOptions.Option2 = 500;
    });

    services.AddRazorPages();
}

Im folgenden Code werden die Optionswerte angezeigt:

public class Test2Model : PageModel
{
    private readonly IOptions<MyOptions> _optionsDelegate;

    public Test2Model(IOptions<MyOptions> optionsDelegate )
    {
        _optionsDelegate = optionsDelegate;
    }

    public ContentResult OnGet()
    {
        return Content($"Option1: {_optionsDelegate.Value.Option1} \n" +
                       $"Option2: {_optionsDelegate.Value.Option2}");
    }
}

Im vorherigen Beispiel wurden die Werte von Option1 und Option2 in appsettings.json angegeben und anschließend vom konfigurierten Delegaten überschrieben.

Hostkonfiguration und App-Konfiguration im Vergleich

Bevor die App konfiguriert und gestartet wird, wird ein Host konfiguriert und gestartet. Der Host ist verantwortlich für das Starten der App und das Verwalten der Lebensdauer. Die App und der Host werden mit den in diesem Thema beschriebenen Konfigurationsanbietern konfiguriert. Schlüssel-Wert-Paare der Hostkonfiguration sind ebenfalls in der globalen App-Konfiguration enthalten. Weitere Informationen dazu, wie Konfigurationsanbieter beim Erstellen des Hosts verwendet werden, und wie sich Konfigurationsquellen auf die Hostkonfiguration auswirken, finden Sie unter ASP.NET Core – Grundlagen.

Standardhostkonfiguration

Ausführliche Informationen zur Standardkonfiguration bei Verwendung des Webhosts finden Sie in der ASP.NET Core 2.2-Version dieses Themas.

  • Die Konfiguration des Hosts wird durch Folgendes festgelegt:
    • Umgebungsvariablen mit dem Präfix DOTNET_ (z. B. DOTNET_ENVIRONMENT), die den Umgebungsvariablen-Konfigurationsanbieter verwenden. Das Präfix (DOTNET_) wird beim Laden der Schlüssel-Wert-Paare der Konfiguration entfernt.
    • Befehlszeilenargumente, die den Befehlszeilen-Konfigurationsanbieter verwenden
  • Die Webhost-Standardkonfiguration wird eingerichtet (ConfigureWebHostDefaults):
    • Kestrel wird als Webserver verwendet und mithilfe der Konfigurationsanbieter der App konfiguriert.
    • Fügen Sie Middleware zum Filtern von Hosts hinzu.
    • Fügen Sie Middleware für weitergeleitete Header hinzu, wenn die Umgebungsvariable ASPNETCORE_FORWARDEDHEADERS_ENABLED auf true festgelegt ist.
    • Aktivieren Sie die IIS-Integration.

Sonstige Konfiguration

Dieses Thema bezieht sich nur auf App-Konfigurationen. Andere Aspekte des Ausführens und Hostings von ASP.NET Core-Apps werden mithilfe von Konfigurationsdateien konfiguriert, die in diesem Thema nicht behandelt werden:

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

Weitere Informationen zum Migrieren der App-Konfiguration aus früheren Versionen von ASP.NET finden Sie unter Migrieren von ASP.NET zu ASP.NET Core.

Hinzufügen von Konfigurationen aus einer externen Assembly

Eine IHostingStartup-Implementierung ermöglicht das Hinzufügen von Erweiterungen zu einer App beim Start von einer externen Assembly außerhalb der Startup-Klasse der App aus. Weitere Informationen finden Sie unter Verwenden von Hostingstartassemblys in ASP.NET Core.

Zusätzliche Ressourcen