Configurazione in ASP.NET Core

Di Rick Anderson e Kirk Larkin

Nota

Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 8 di questo articolo.

Avviso

Questa versione di ASP.NET Core non è più supportata. Per altre informazioni, vedere Criteri di supporto di .NET e .NET Core. Per la versione corrente, vedere la versione .NET 8 di questo articolo.

Importante

Queste informazioni si riferiscono a un prodotto non definitive che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.

Per la versione corrente, vedere la versione .NET 8 di questo articolo.

La configurazione dell'applicazione in ASP.NET Core viene eseguita usando uno o più provider di configurazione. I provider di configurazione leggono i dati di configurazione da coppie chiave-valore usando diverse origini di configurazione:

  • File di impostazioni, ad esempio appsettings.json
  • Variabili di ambiente
  • Azure Key Vault
  • Configurazione app di Azure
  • Argomenti della riga di comando
  • Provider personalizzati, installati o creati
  • File della directory
  • Oggetti .NET in memoria

Questo articolo offre informazioni sulla configurazione in ASP.NET Core. Per informazioni sull'uso della configurazione nelle app console, vedere Configurazione di .NET.

Per Blazor indicazioni sulla configurazione, che aggiunge o sostituisce le linee guida in questo nodo, vedere ASP.NET Configurazione coreBlazor.

Configurazione dell'applicazione e dell'host

Le app ASP.NET Core configurano e avviano un host. L'host è responsabile della gestione dell'avvio e della durata delle app. I modelli di ASP.NET Core creano un WebApplicationBuilder che contiene l'host. Sebbene parte della configurazione possa essere eseguita sia nel provider di configurazione dell'host che nel provider di configurazione dell'applicazione, in generale solo la configurazione necessaria all'host deve essere eseguita nella configurazione dell'host.

La configurazione dell'applicazione è la priorità più alta ed è descritta nel dettaglio nella sezione successiva. La configurazione dell'host segue la configurazione dell'applicazione ed è descritta in questo articolo.

Origini della configurazione dell'applicazione predefinite

Le app Web ASP.NET Core create con dotnet new o Visual Studio generano il codice seguente:

var builder = WebApplication.CreateBuilder(args);

WebApplication.CreateBuilder inizializza una nuova istanza della classe WebApplicationBuilder con valori predefiniti preconfigurati. Il WebApplicationBuilder (builder) inizializzato offre la configurazione predefinita per l'app nell'ordine seguente, dalla priorità più alta a quella più bassa:

  1. Argomenti della riga di comando che usano il provider di configurazione della riga di comando.
  2. Variabili di ambiente senza prefisso che usano il provider di configurazione delle variabili di ambiente senza prefisso.
  3. Segreti dell'utente quando l'app viene eseguita nell'ambiente Development.
  4. appsettings.{Environment}.json usando il provider di configurazione JSON. Ad esempio, appsettings.Production.json e appsettings.Development.json.
  5. appsettings.json usando il provider di configurazione JSON.
  6. Un fallback alla configurazione dell'host descritto nella sezione successiva.

Origini della configurazione dell'host predefinite

L'elenco seguente contiene le origini di configurazione host predefinite dalla priorità più alta alla più bassa per WebApplicationBuilder:

  1. Argomenti della riga di comando che usano il provider di configurazione della riga di comando
  2. Variabili di ambiente con prefisso DOTNET_ che usano il provider di configurazione delle variabili di ambiente.
  3. Variabili di ambiente con prefisso ASPNETCORE_ che usano il provider di configurazione delle variabili di ambiente.

Per l'host generico .NET e l'host Web, le origini di configurazione host predefinite dalla priorità più alta alla più bassa sono:

  1. Variabili di ambiente con prefisso ASPNETCORE_ che usano il provider di configurazione delle variabili di ambiente.
  2. Argomenti della riga di comando che usano il provider di configurazione della riga di comando
  3. Variabili di ambiente con prefisso DOTNET_ che usano il provider di configurazione delle variabili di ambiente.

Quando un valore di configurazione viene impostato nella configurazione dell'host e dell'applicazione, viene usata la configurazione dell'applicazione.

Variabili dell'host

Le variabili seguenti vengono bloccate in anticipo durante l'inizializzazione dei generatori di host e non possono essere influenzate dalla configurazione dell'applicazione:

Ogni altra impostazione dell'host viene letta dalla configurazione dell'applicazione anziché dalla configurazione dell'host.

URLS è una delle numerose impostazioni dell'host comuni che non è un'impostazione bootstrap. Come tutte le altre impostazioni dell'host non presenti nell'elenco precedente, URLS viene letta successivamente dalla configurazione dell'applicazione. Poiché la configurazione dell'host è un fallback per la configurazione dell'applicazione, la configurazione dell'host può essere usata per impostare URLS, ma verrà sostituita da qualsiasi origine di configurazione nella configurazione dell'applicazione, come appsettings.json.

Per altre informazioni, vedere Modificare la radice del contenuto, il nome dell'app e l'ambiente e Modificare la radice del contenuto, il nome dell'app e l'ambiente in base alle variabili di ambiente o alla riga di comando

Le sezioni rimanenti di questo articolo fanno riferimento alla configurazione dell'applicazione.

Provider di configurazione dell'applicazione

Il codice seguente visualizza i provider di configurazione abilitati nell'ordine in cui sono stati aggiunti:

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

L'elenco precedente delle origini di configurazione predefinite dalla priorità più alta alla priorità più bassa mostra i provider nell'ordine opposto in cui vengono aggiunti all'applicazione generata dal modello. Ad esempio, il provider di configurazione JSON viene aggiunto prima del provider di configurazione della riga di comando.

I provider di configurazione aggiunti successivamente hanno priorità più alta e sostituiscono le impostazioni delle chiavi precedenti. Ad esempio, se MyKey è impostato sia in appsettings.json che nell'ambiente, viene usato il valore dell'ambiente. Quando si usano i provider di configurazione predefiniti, il provider di configurazione della riga di comando sostituisce tutti gli altri provider.

Per altre informazioni su CreateBuilder, vedere Impostazioni predefinite del generatore.

appsettings.json

Considerare il file appsettings.json seguente:

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

Il codice seguente del download di esempio visualizza diverse impostazioni delle configurazioni precedenti:

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

Il JsonConfigurationProvider predefinito carica la configurazione nell'ordine seguente:

  1. appsettings.json
  2. appsettings.{Environment}.json : ad esempio, i file appsettings.Production.json e appsettings.Development.json. La versione dell'ambiente del file viene caricata in base a IHostingEnvironment.EnvironmentName. Per altre informazioni, vedere Usare più ambienti in ASP.NET Core.

I valori appsettings.{Environment}.json sostituiscono le chiavi in appsettings.json. Ad esempio, per impostazione predefinita:

  • Nello sviluppo la configurazione appsettings.Development.json sovrascrive i valori trovati in appsettings.json.
  • Nella produzione la configurazione appsettings.Production.json sovrascrive i valori trovati in appsettings.json. Ad esempio, durante la distribuzione dell'app in Azure.

Se è necessario garantire un valore di configurazione, vedere GetValue. L'esempio precedente legge solo le stringhe e non supporta un valore predefinito.

Quando si usa la configurazione predefinita, i file appsettings.json e appsettings.{Environment}.json sono abilitati con reloadOnChange: true. Le modifiche apportate al appsettings.json file e appsettings.{Environment}.json dopo l'avvio dell'app vengono lette dal provider di configurazione JSON.

Commenti in appsettings.json

I commenti in appsettings.json e appsettings.{Environment}.json i file sono supportati usando commenti in stile JavaScript o C#.

Associare dati di configurazione gerarchici usando il modello di opzioni

Il modo preferito per leggere i valori di configurazione correlati prevede l'uso del modello di opzioni. Ad esempio, per leggere i valori di configurazione seguenti:

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

Creare la classe PositionOptions seguente:

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

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

Una classe di opzioni:

  • Deve essere non astratta con un costruttore pubblico senza parametri.
  • Tutte le proprietà di lettura/scrittura pubbliche del tipo sono associate.
  • I campi non sono associati. Nel codice precedente Position non è associato. Il campo Position viene usato in modo che la stringa "Position" non debba essere hardcoded nell'app quando la classe viene associata a un provider di configurazione.

Il codice seguente:

  • Chiama ConfigurationBinder.Bind per associare la classe PositionOptions alla sezione Position.
  • Visualizza i dati di configurazione di Position.
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}");
    }
}

Nel codice precedente, per impostazione predefinita, le modifiche apportate al file di configurazione JSON dopo l'avvio dell'app vengono lette.

ConfigurationBinder.Get<T> associa e restituisce il tipo specificato. ConfigurationBinder.Get<T> può risultare più utile rispetto all'uso di ConfigurationBinder.Bind. Il codice seguente mostra come usare ConfigurationBinder.Get<T> con la classe PositionOptions:

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

Nel codice precedente, per impostazione predefinita, le modifiche apportate al file di configurazione JSON dopo l'avvio dell'app vengono lette.

Un approccio alternativo quando si usa il modello opzioni consiste nell'associare la sezione Position e aggiungerla al contenitore del servizio di inserimento di dipendenze. Nel codice seguente PositionOptions viene aggiunta al contenitore del servizio con Configure e associata alla configurazione:

using ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

Quando si usa il codice precedente, il codice seguente legge le opzioni di posizione:

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

Nel codice precedente le modifiche al file di configurazione JSON dopo l'avvio dell'app non vengono lette. Per leggere le modifiche dopo l'avvio dell'app, usare IOptionsSnapshot.

Quando si usa la configurazione predefinita, i file appsettings.json e appsettings.{Environment}.json sono abilitati con reloadOnChange: true. Le modifiche apportate al appsettings.json file e appsettings.{Environment}.json dopo l'avvio dell'app vengono lette dal provider di configurazione JSON.

Per informazioni sull'aggiunta di file di configurazione JSON aggiuntivi, vedere Provider di configurazione JSON in questo documento.

Combinazione della raccolta di servizi

Considerare il codice seguente che registra i servizi e configura le opzioni:

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();

I gruppi correlati di registrazioni possono essere spostati in un metodo di estensione per registrare i servizi. Ad esempio, i servizi di configurazione vengono aggiunti alla classe seguente:

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

        public static IServiceCollection AddMyDependencyGroup(
             this IServiceCollection services)
        {
            services.AddScoped<IMyDependency, MyDependency>();
            services.AddScoped<IMyDependency2, MyDependency2>();

            return services;
        }
    }
}

I servizi rimanenti vengono registrati in una classe simile. Il codice seguente usa i nuovi metodi di estensione per registrare i servizi:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

Nota: ogni metodo di estensione services.Add{GROUP_NAME} aggiunge e configura potenzialmente i servizi. Ad esempio, AddControllersWithViews aggiunge i controller MVC dei servizi con visualizzazioni richiesti e AddRazorPages aggiunge le pagina Razor dei servizi richieste.

Sicurezza e segreti dell'utente

Linee guida per i dati di configurazione:

  • Non archiviare mai la password o altri dati sensibili nel codice del provider di configurazione o in file di configurazione di testo normale. Per l'archiviazione di segreti per lo sviluppo, è possibile usare lo strumento Secret Manager.
  • Non usare i segreti di produzione in ambienti di sviluppo o di test.
  • Specificare i segreti all'esterno del progetto in modo che non possano essere inavvertitamente inviati a un repository del codice sorgente.
  • Le app di produzione devono usare il flusso di autenticazione più sicuro disponibile. Per altre informazioni, vedere Proteggere i flussi di autenticazione.

Per impostazione predefinita, l'origine di configurazione dei segreti utente viene registrata dopo le origini di configurazione JSON. Pertanto, le chiavi dei segreti dell'utente hanno la precedenza sulle chiavi in appsettings.json e appsettings.{Environment}.json.

Per altre informazioni sull'archiviazione di password o altri dati sensibili:

Variabili di ambiente senza prefisso

Le variabili di ambiente senza prefisso sono variabili di ambiente diverse da quelle precedute da ASPNETCORE_ o DOTNET_. Ad esempio, i modelli di applicazione Web ASP.NET Core impostano "ASPNETCORE_ENVIRONMENT": "Development" in launchSettings.json. Per altre informazioni sulle variabili di ambiente ASPNETCORE_ e DOTNET_, vedere:

Quando si usa la configurazione predefinita, EnvironmentVariablesConfigurationProvider carica la configurazione dalle coppie chiave-valore delle variabili di ambiente dopo la lettura di appsettings.json, appsettings.{Environment}.json e dei segreti dell'utente. Therefore, i valori di chiave letti dall'ambiente sostituiscono i valori letti da appsettings.json, appsettings.{Environment}.json e dai segreti dell'utente.

Il separatore : non funziona con le chiavi gerarchiche delle variabili di ambiente in tutte le piattaforme. Ad esempio, il : separatore non è supportato da Bash. Il doppio carattere di sottolineatura, __, è:

  • Supportato da tutte le piattaforme.
  • Sostituito automaticamente da due punti, :.

I comandi seguenti:

  • Impostano le chiavi e i valori di ambiente dell'esempio precedente in Windows.
  • Testano le impostazioni quando viene usato il download di esempio. Il comando dotnet run deve essere eseguito nella directory del progetto.
set MyKey="My key from Environment"
set Position__Title=Environment_Editor
set Position__Name=Environment_Rick
dotnet run

Le impostazioni dell'ambiente precedenti:

  • Sono impostate solo nei processi avviati dalla finestra di comando in cui sono stati impostate.
  • Non verranno lette dai browser avviati con Visual Studio.

I comandi setx seguenti possono essere usati per impostare le chiavi e i valori di ambiente in Windows. A differenza di set, le impostazioni setx vengono mantenute. /M imposta la variabile nell'ambiente di sistema. Se non viene usata l'opzione /M, viene impostata una variabile di ambiente dell'utente.

setx MyKey "My key from setx Environment" /M
setx Position__Title Environment_Editor /M
setx Position__Name Environment_Rick /M

Per verificare che i comandi precedenti sostituiscano appsettings.json e appsettings.{Environment}.json:

  • Con Visual Studio: uscire e riavviare Visual Studio.
  • Con l'interfaccia della riga di comando: avviare una nuova finestra di comando e immettere dotnet run.

Chiamare AddEnvironmentVariables con una stringa per specificare un prefisso per le variabili di ambiente:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

Nel codice precedente:

Il prefisso viene rimosso quando vengono lette le coppie chiave-valore della configurazione.

I comandi seguenti testano il prefisso personalizzato:

set MyCustomPrefix_MyKey="My key with MyCustomPrefix_ Environment"
set MyCustomPrefix_Position__Title=Editor_with_customPrefix
set MyCustomPrefix_Position__Name=Environment_Rick_cp
dotnet run

La configurazione predefinita carica le variabili di ambiente e gli argomenti della riga di comando con prefisso DOTNET_ e ASPNETCORE_. I prefissi DOTNET_ e ASPNETCORE_ vengono usati da ASP.NET Core per la configurazione dell'host e dell'app, ma non per la configurazione dell'utente. Per altre informazioni sulla configurazione dell'host e dell'app, vedere Host generico .NET.

In Servizio app di Azure selezionare Nuova impostazione applicazione nella pagina Impostazioni > Configurazione. Le impostazioni applicazione del Servizio app di Azure sono:

  • Crittografato in e rest trasmesso tramite un canale crittografato.
  • Esposte come variabili di ambiente.

Per altre informazioni, vedere App di Azure: Eseguire l'override della configurazione delle app usando il portale di Azure.

Per informazioni sulle stringhe di connessione del database di Azure, vedere Prefissi della stringa di connessione.

Denominazione delle variabili di ambiente

I nomi delle variabili di ambiente riflettono la struttura di un file appsettings.json. Ogni elemento nella gerarchia è separato da un doppio carattere di sottolineatura (preferibile) o due punti. Quando la struttura dell'elemento include una matrice, l'indice della matrice deve essere considerato come un nome di elemento aggiuntivo in questo percorso. Si consideri il file appsettings.json seguente e i relativi valori equivalenti rappresentati come variabili di ambiente.

appsettings.json

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

variabili di ambiente

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

Variabili di ambiente impostate nel file launchSettings.json generato

Variabili di ambiente impostate in launchSettings.json sostituiscono quelle impostate nell'ambiente di sistema. Ad esempio, i modelli Web ASP.NET Core generano un file launchSettings.json che imposta la configurazione dell'endpoint su:

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

La configurazione di applicationUrl imposta la variabile di ambiente ASPNETCORE_URLS e sostituisce i valori impostati nell'ambiente.

Carattere di escape per le variabili di ambiente in Linux

In Linux il valore delle variabili di ambiente degli URL deve essere preceduto da un carattere di escape in modo che systemd possa analizzarle. Usare lo strumento linux systemd-escape che restituisce http:--localhost:5001

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

Visualizzare le variabili di ambiente

Il codice seguente visualizza le variabili di ambiente e i valori all'avvio dell'applicazione, utile durante il debug delle impostazioni di ambiente:

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

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

Riga di comando

Quando si usa la configurazione predefinita, CommandLineConfigurationProvider carica la configurazione dalle coppie chiave-valore degli argomenti della riga di comando dopo le origini di configurazione seguenti:

  • File appsettings.json e appsettings.{Environment}.json.
  • Segreti dell'app nell'ambiente di sviluppo.
  • variabili di ambiente.

Per impostazione predefinita, i valori di configurazione impostati nella riga di comando sostituiscono i valori di configurazione impostati con tutti gli altri provider di configurazione.

Argomenti della riga di comando

Il comando seguente imposta chiavi e valori usando =:

dotnet run MyKey="Using =" Position:Title=Cmd Position:Name=Cmd_Rick

Il comando seguente imposta chiavi e valori usando /:

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

Il comando seguente imposta chiavi e valori usando --:

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

Il valore di chiave:

  • Deve seguire = o la chiave deve avere un prefisso -- o / quando il valore segue uno spazio.
  • Non è richiesto se viene usato =. Ad esempio: MySetting=.

Nello stesso comando, non mischiare coppie chiave-valore di argomenti della riga di comando che usano = con coppie chiave-valore che usano uno spazio.

Mapping di sostituzione

I mapping di sostituzione consentono di usare la logica di sostituzione del nome della chiave. Specificare un dizionario delle sostituzioni al metodo AddCommandLine.

Quando viene utilizzato il dizionario dei mapping di sostituzione, nel dizionario viene controllata la presenza di una chiave corrispondente alla chiave fornita da un argomento della riga di comando. Se la chiave della riga di comando viene trovata nel dizionario, il valore del dizionario viene passato nuovamente per impostare la coppia chiave-valore nella configurazione dell'app. Un mapping di sostituzione è necessario per le chiavi della riga di comando con un trattino singolo (-) come prefisso.

Regole principali del dizionario dei mapping di sostituzione:

  • Le sostituzioni devono iniziare con - o --.
  • Il dizionario dei mapping di sostituzione non deve contenere chiavi duplicate.

Per usare un dizionario dei mapping di sostituzione, passarlo nella chiamata a AddCommandLine:


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();

Per testare la sostituzione delle chiavi è possibile eseguire il comando seguente:

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

Il codice seguente mostra i valori di chiave per le chiavi sostituite:

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"]}'");
    }
}

Per le app che usano i mapping di sostituzione, la chiamata a CreateDefaultBuilder non deve passare argomenti. La chiamata AddCommandLine del metodo CreateDefaultBuilder non include sostituzioni mappate e non è possibile passare il dizionario dei mapping di sostituzione a CreateDefaultBuilder. La soluzione non consiste nel passare gli argomenti a CreateDefaultBuilder ma nel consentire al metodo AddCommandLine del metodo ConfigurationBuilder di elaborare entrambi gli argomenti e il dizionario dei mapping di sostituzione.

Impostare gli argomenti dell'ambiente e della riga di comando con Visual Studio

Gli argomenti dell'ambiente e della riga di comando possono essere impostati in Visual Studio dalla finestra dei profili di avvio:

  • In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e selezionare Proprietà.
  • Selezionare la scheda Debug > Generale e selezionare Aprire interfaccia utente profili di avvio debug.

Dati di configurazione gerarchici

L'API di configurazione legge i dati di configurazione gerarchici rendendoli flat grazie all'uso di un delimitatore nelle chiavi di configurazione.

Il download di esempio contiene il file appsettings.json seguente:

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

Il codice seguente del download di esempio visualizza diverse impostazioni delle configurazioni:

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

Il modo preferito per leggere i dati di configurazione gerarchici prevede l'uso del modello di opzioni. Per altre informazioni, vedere Associare dati di configurazione gerarchici in questo documento.

I metodi GetSection e GetChildren sono disponibili per isolare le sezioni e gli elementi figlio di una sezione nei dati di configurazione. Questi metodi sono descritti più avanti in GetSection, GetChildren ed Exists.

Chiavi e valori di configurazione

Avviso

Questo articolo illustra l'uso di stringa di connessione. Con un database locale l'utente non deve essere autenticato, ma nell'ambiente di produzione stringa di connessione talvolta include una password per l'autenticazione. Una credenziale della password del proprietario della risorsa (ROPC) è un rischio per la sicurezza che deve essere evitato nei database di produzione. Le app di produzione devono usare il flusso di autenticazione più sicuro disponibile. Per altre informazioni sull'autenticazione per le app distribuite in ambienti di test o di produzione, vedere Proteggere i flussi di autenticazione.

Chiavi di configurazione:

  • non viene fatta distinzione tra maiuscole e minuscole. Ad esempio, ConnectionString e connectionstring vengono considerate chiavi equivalenti.
  • Se una chiave e un valore sono impostati in più provider di configurazione, viene usato il valore dell'ultimo provider aggiunto. Per altre informazioni, vedere Configurazione predefinita.
  • Chiavi gerarchica
    • Nell'ambito dell'API di configurazione, il separatore due punti (:) funziona in tutte le piattaforme.
    • Nelle variabili di ambiente, un separatore due punti potrebbe non funzionare in tutte le piattaforme. Il doppio carattere di sottolineatura, __, è supportato da tutte le piattaforme e viene convertito automaticamente nei due punti :.
    • In Azure Key Vault le chiavi gerarchiche usano -- come separatore. Il provider di configurazione di Azure Key Vault sostituisce automaticamente -- con : quando i segreti vengono caricati nella configurazione dell'app.
  • Il ConfigurationBinder supporta l'associazione di matrici agli oggetti usando gli indici delle matrici nelle chiavi di configurazione. L'associazione di matrici è descritta nella sezione Associare una matrice a una classe.

Valori di configurazione:

  • sono stringhe.
  • I valori null non possono essere archiviati nella configurazione o associati a oggetti.

Provider di configurazione

La tabella seguente mostra i provider di configurazione disponibili per le app ASP.NET Core.

Provider Fornisce la configurazione da
Azure Key Vault configuration provider (Provider di configurazione di Azure Key Vault) Azure Key Vault
Provider di configurazione app di Azure Configurazione app di Azure
Provider di configurazione della riga di comando Parametri della riga di comando
Provider di configurazione personalizzato Origine personalizzata
Provider di configurazione delle variabili di ambiente Variabili di ambiente
Provider di configurazione file File INI, JSON e XML
Provider di configurazione chiave-per-file File della directory
Provider di configurazione della memoria Raccolte in memoria
Segreti utente File nella directory dei profili utente

Le origini di configurazione vengono lette nell'ordine in cui vengono specificati i rispetti provider di configurazione. Ordinare i provider di configurazione nel codice in base alle priorità per le origini di configurazione sottostanti richieste dall'app.

Una sequenza tipica di provider di configurazione è:

  1. appsettings.json
  2. appsettings.{Environment}.json
  3. Segreti utente
  4. Variabili di ambiente che usano il provider di configurazione delle variabili di ambiente.
  5. Argomenti della riga di comando che usano il provider di configurazione della riga di comando.

È pratica comune aggiungere il provider di configurazione della riga di comando per ultimo in una serie di provider per consentire agli argomenti della riga di comando di sostituire la configurazione impostata da altri provider.

La sequenza di provider precedente è usata nella configurazione predefinita.

Prefissi della stringa di connessione

Avviso

Questo articolo illustra l'uso di stringa di connessione. Con un database locale l'utente non deve essere autenticato, ma nell'ambiente di produzione stringa di connessione talvolta include una password per l'autenticazione. Una credenziale della password del proprietario della risorsa (ROPC) è un rischio per la sicurezza che deve essere evitato nei database di produzione. Le app di produzione devono usare il flusso di autenticazione più sicuro disponibile. Per altre informazioni sull'autenticazione per le app distribuite in ambienti di test o di produzione, vedere Proteggere i flussi di autenticazione.

L'API di configurazione ha regole di elaborazione speciali per quattro variabili di ambiente della stringa di connessione. Queste stringhe di connessione sono coinvolte nella configurazione delle stringhe di connessione di Azure per l'ambiente dell'app. Le variabili di ambiente con i prefissi indicati nella tabella vengono caricate nell'app con la configurazione predefinita o quando non viene specificato alcun prefisso per AddEnvironmentVariables.

Prefisso della stringa di connessione Provider
CUSTOMCONNSTR_ Provider personalizzato
MYSQLCONNSTR_ MySQL
SQLAZURECONNSTR_ Database SQL di Azure
SQLCONNSTR_ SQL Server

Quando una variabile di ambiente viene individuata e caricata nella configurazione con uno qualsiasi dei quattro prefissi indicati nella tabella:

  • La chiave di configurazione viene creata rimuovendo il prefisso della variabile di ambiente e aggiungendo una sezione per la chiave di configurazione (ConnectionStrings).
  • Viene creata una nuova coppia chiave-valore della configurazione che rappresenta il provider di connessione al database (ad eccezione di CUSTOMCONNSTR_, che non ha un provider dichiarato).
Chiave della variabile di ambiente Chiave di configurazione convertita Voce di configurazione del provider
CUSTOMCONNSTR_{KEY} ConnectionStrings:{KEY} Voce di configurazione non creata.
MYSQLCONNSTR_{KEY} ConnectionStrings:{KEY} Chiave: ConnectionStrings:{KEY}_ProviderName:
Valore: MySql.Data.MySqlClient
SQLAZURECONNSTR_{KEY} ConnectionStrings:{KEY} Chiave: ConnectionStrings:{KEY}_ProviderName:
Valore: System.Data.SqlClient
SQLCONNSTR_{KEY} ConnectionStrings:{KEY} Chiave: ConnectionStrings:{KEY}_ProviderName:
Valore: System.Data.SqlClient

Provider di configurazione file

FileConfigurationProvider è la classe base per il caricamento della configurazione dal file system. I provider di configurazione seguenti derivano da FileConfigurationProvider:

Provider di configurazione INI

IniConfigurationProvider carica la configurazione da coppie chiave-valore di file INI in fase di esecuzione.

Il codice seguente aggiunge diversi provider di configurazione:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddIniFile("MyIniConfig.ini", optional: true, reloadOnChange: true)
    .AddIniFile($"MyIniConfig.{builder.Environment.EnvironmentName}.ini",
                optional: true, reloadOnChange: true);

builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

Nel codice precedente le impostazioni nei file MyIniConfig.ini e MyIniConfig.{Environment}.ini sono sostituite dalle impostazioni in:

Il download di esempio contiene il file MyIniConfig.ini seguente:

MyKey="MyIniConfig.ini Value"

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

[Logging:LogLevel]
Default=Information
Microsoft=Warning

Il codice seguente del download di esempio visualizza diverse impostazioni delle configurazioni precedenti:

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

Provider di configurazione JSON

Carica JsonConfigurationProvider la configurazione dalle coppie chiave-valore del file JSON.

Gli overload possono specificare:

  • Se il file è facoltativo.
  • Se la configurazione viene ricaricata se viene modificato il file.

Osservare il codice seguente:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddJsonFile("MyConfig.json",
        optional: true,
        reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

Il codice precedente:

In genere non si vuole che un file JSON personalizzato sostituisci i valori impostati nel provider di configurazione delle variabili di ambiente e nel provider di configurazione della riga di comando.

Provider di configurazione XML

Il XmlConfigurationProvider carica la configurazione da coppie chiave-valore di file XML in fase di esecuzione.

Il codice seguente aggiunge diversi provider di configurazione:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddXmlFile("MyXMLFile.xml", optional: true, reloadOnChange: true)
    .AddXmlFile($"MyXMLFile.{builder.Environment.EnvironmentName}.xml",
                optional: true, reloadOnChange: true);

builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

Nel codice precedente le impostazioni nei file MyXMLFile.xml e MyXMLFile.{Environment}.xml sono sostituite dalle impostazioni in:

Il download di esempio contiene il file MyXMLFile.xml seguente:

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

Il codice seguente del download di esempio visualizza diverse impostazioni delle configurazioni precedenti:

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

La ripetizione di elementi che usano lo stesso nome di elemento funziona se si usa l'attributo name per distinguere gli elementi:

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

Il codice seguente legge il file di configurazione precedente e visualizza le chiavi e i valori:

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

È possibile usare attributi per fornire valori:

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

Il file di configurazione precedente carica le chiavi seguenti con value:

  • key:attribute
  • section:key:attribute

Provider di configurazione chiave-per-file

Il KeyPerFileConfigurationProvider usa i file di una directory come coppie chiave-valore della configurazione. La chiave è il nome del file. Il valore contiene il contenuto del file. Il provider di configurazione chiave-per-file viene usato negli scenari di hosting di Docker.

Per attivare la configurazione chiave-per-file, chiamare il metodo di estensione AddKeyPerFile su un'istanza di ConfigurationBuilder. Il directoryPath per i file deve essere un percorso assoluto.

Gli overload consentono di specificare:

  • Un delegato Action<KeyPerFileConfigurationSource> che configura l'origine.
  • Se la directory è facoltativa e il percorso della directory.

Il doppio carattere di sottolineatura (__) viene usato come delimitatore per le chiavi di configurazione nei nomi dei file. Ad esempio, il nome di file Logging__LogLevel__System produce la chiave di configurazione Logging:LogLevel:System.

Chiamare ConfigureAppConfiguration quando si crea l'host per specificare la configurazione dell'app:

.ConfigureAppConfiguration((hostingContext, config) =>
{
    var path = Path.Combine(
        Directory.GetCurrentDirectory(), "path/to/files");
    config.AddKeyPerFile(directoryPath: path, optional: true);
})

Provider di configurazione della memoria

Il MemoryConfigurationProvider usa una raccolta in memoria come coppie chiave-valore della configurazione.

Il codice seguente aggiunge una raccolta di memoria al sistema di configurazione:

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.Configuration.AddInMemoryCollection(Dict);
builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

Il codice seguente del download di esempio visualizza le impostazioni delle configurazioni precedenti:

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

Nel codice precedente config.AddInMemoryCollection(Dict) viene aggiunto dopo i provider di configurazione predefiniti. Per un esempio di ordinamento dei provider di configurazione, vedere Provider di configurazione JSON.

Vedere Associare una matrice per un altro esempio che usa MemoryConfigurationProvider.

Configurazione di endpoint Kestrel

La configurazione di endpoint specifica di Kestrel sostituisce tutte le configurazioni di endpoint tra server. Le configurazioni di endpoint tra server includono:

Si consideri il file appsettings.json seguente usato in un'app Web ASP.NET Core:

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

Quando il markup evidenziato precedente viene usato in un'app Web ASP.NET Core e l'app viene avviata dalla riga di comando con la configurazione dell'endpoint tra server seguente:

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

Kestrel si associa all'endpoint configurato specificatamente per Kestrel nel file appsettings.json (https://localhost:9999) e non in https://localhost:7777.

Si consideri l'endpoint specifico di Kestrel configurato come variabile di ambiente:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

nella variabile di ambiente precedente Https è il nome dell'endpoint specifico di Kestrel. Il file appsettings.json precedente definisce anche un endpoint specifico di Kestrel denominato Https. Per impostazione predefinita, le variabili di ambiente che usano il provider di configurazione delle variabili di ambiente vengono lette dopo appsettings.{Environment}.json, di conseguenza la variabile di ambiente precedente viene usata per l'endpoint Https.

GetValue

ConfigurationBinder.GetValue estrae un valore dalla configurazione con una chiave specificata e lo converte nel tipo specificato:

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

Nel codice precedente, se NumberKey non viene trovato nella configurazione, viene usato il valore predefinito di 99.

GetSection, GetChildren ed Exists

Per gli esempi che seguono, prendere in considerazione il file MySubsection.json seguente:

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

Il codice seguente aggiunge MySubsection.json ai provider di configurazione:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddJsonFile("MySubsection.json",
                 optional: true,
                 reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

GetSection

IConfiguration.GetSection restituisce una sottosezione della configurazione con la chiave di sottosezione specificata.

Il codice seguente restituisce i valori per section1:

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"]}'");
    }
}

Il codice seguente restituisce i valori per section2:subsection0:

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 non restituisce mai null. Se non viene trovata una sezione corrispondente, viene restituita una IConfigurationSection vuota.

Quando GetSection restituisce una sezione corrispondente, Value non viene compilata. Quando la sezione esiste, vengono restituiti Key e Path.

GetChildren ed Exists

Il codice seguente chiama IConfiguration.GetChildren e restituisce i valori per section2:subsection0:

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

Il codice precedente chiama ConfigurationExtensions.Exists per verificare che la sezione esista:

Associare una matrice

Il ConfigurationBinder.Bind supporta l'associazione di matrici agli oggetti usando gli indici delle matrici nelle chiavi di configurazione. Qualsiasi formato di matrice che espone un segmento chiave numerico supporta l'associazione di matrici a una matrice di classi POCO.

Si consideri MyArray.json del download di esempio:

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

Il codice seguente aggiunge MyArray.json ai provider di configurazione:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddJsonFile("MyArray.json",
                 optional: true,
                 reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

Il codice seguente legge la configurazione e visualizza i valori:

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>();
        if (_array == null)
        {
            throw new ArgumentNullException(nameof(_array));
        }
        string s = String.Empty;

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

        return Content(s);
    }
}
public class ArrayExample
{
    public string[]? Entries { get; set; } 
}

Il codice precedente restituisce l'output seguente:

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

Nell'output precedente Index 3 ha il valore value40, corrispondente a "4": "value40", in MyArray.json. Gli indici di matrice associati sono continui e non associati all'indice delle chiavi di configurazione. Il binder di configurazione non supporta l'associazione di valori Null o la creazione di voci Null negli oggetti associati.

Provider di configurazione personalizzato

L'app di esempio dimostra come creare un provider di configurazione di base che legge le coppie chiave-valore di configurazione da un database usando Entity Framework (EF).

Il provider ha le caratteristiche seguenti:

  • Il database in memoria di Entity Framework viene usato a scopo dimostrativo. Per usare un database che richiede una stringa di connessione, implementare un ConfigurationBuilder secondario per fornire la stringa di connessione da un altro provider di configurazione.
  • Il provider legge una tabella di database in una configurazione all'avvio. Il provider non esegue una query sul database per ogni chiave.
  • Il ricaricamento in caso di modifica non è implementato, quindi l'aggiornamento del database dopo l'avvio dell'app non ha alcun effetto sulla configurazione dell'app.

Definire un'entità EFConfigurationValue per l'archiviazione dei valori di configurazione nel database.

Models/EFConfigurationValue.cs:

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

Aggiungere EFConfigurationContext per archiviare i valori configurati e accedervi.

EFConfigurationProvider/EFConfigurationContext.cs:

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

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

Creare una classe che implementi IConfigurationSource.

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

Creare il provider di configurazione personalizzato ereditando da ConfigurationProvider. Il provider di configurazione inizializza il database quando è vuoto. Poiché nelle chiavi di configurazione non viene fatta distinzione tra maiuscole e minuscole, il dizionario usato per inizializzare il database viene creato con l'operatore di confronto senza distinzione tra maiuscole e minuscole (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-2005
        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;
    }
}

Un metodo di estensione AddEFConfiguration consente di aggiungere l'origine di configurazione a un ConfigurationBuilder.

Extensions/EntityFrameworkExtensions.cs:

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

Il codice seguente mostra come usare EFConfigurationProvider personalizzato in Program.cs:

//using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

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

var app = builder.Build();

app.Run();

Configurazione dell'accesso con inserimento delle dipendenze

La configurazione può essere inserita nei servizi usando l'inserimento delle dipendenze attraverso la risoluzione del servizio IConfiguration:

public class Service
{
    private readonly IConfiguration _config;

    public Service(IConfiguration config) =>
        _config = config;

    public void DoSomething()
    {
        var configSettingValue = _config["ConfigSetting"];

        // ...
    }
}

Per informazioni su come accedere ai valori usando IConfiguration, vedere GetValue e GetSection, GetChildren ed Exists in questo articolo.

Accedere alla configurazione nelle pagine Razor

Il codice seguente visualizza i dati di configurazione in una pagina Razor:

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

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

Nel codice seguente MyOptions viene aggiunta al contenitore del servizio con Configure e associata alla configurazione:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

Il markup seguente usa la direttiva @injectRazor per risolvere e visualizzare i valori delle opzioni:

@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>

Accedere alla configurazione in un file di visualizzazione MVC

Il codice seguente visualizza i dati di configurazione in una visualizzazione MVC:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

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

Accedere alla configurazione in Program.cs

Il codice seguente accede alla configurazione nel file Program.cs.

var builder = WebApplication.CreateBuilder(args);

var key1 = builder.Configuration.GetValue<string>("KeyOne");

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

var key2 = app.Configuration.GetValue<int>("KeyTwo");
var key3 = app.Configuration.GetValue<bool>("KeyThree");

app.Logger.LogInformation("KeyOne: {KeyOne}", key1);
app.Logger.LogInformation("KeyTwo: {KeyTwo}", key2);
app.Logger.LogInformation("KeyThree: {KeyThree}", key3);

app.Run();

In appsettings.json per l'esempio precedente:

{
  ...
  "KeyOne": "Key One Value",
  "KeyTwo": 1999,
  "KeyThree": true
}

Configurare opzioni con un delegato

Le opzioni configurate in un delegato sostituiscono i valori impostati nei provider di configurazione.

Nel codice seguente viene aggiunto un servizio IConfigureOptions<TOptions> al contenitore di servizi. Viene usato un delegato per configurare i valori per MyOptions:

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();

Il codice seguente visualizza i valori delle opzioni:

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

Nell'esempio precedente i valori di Option1 e Option2 sono specificati in appsettings.json e quindi sostituiti dal delegato configurato.

Host e configurazione delle app

Prima che l'app venga configurata e avviata, viene configurato e avviato un host. L'host è responsabile della gestione dell'avvio e della durata delle app. Sia l'app che l'host vengono configurati tramite i provider di configurazione descritti in questo argomento. Anche le coppie chiave-valore di configurazione dell'host sono incluse nella configurazione dell'app. Per altre informazioni su come vengono usati i provider di configurazione per la creazione dell'host e sugli effetti delle origini di configurazione sulla configurazione dell'host, vedere Panoramica delle nozioni di base su ASP.NET Core.

Configurazione dell'host predefinita

Per informazioni dettagliate sulla configurazione predefinita quando viene usato l'host Web, vedere la versione di questo argomento per ASP.NET Core 2.2.

  • La configurazione dell'host viene fornita da:
  • Viene stabilita la configurazione predefinita dell'host Web (ConfigureWebHostDefaults):
    • Kestrel viene usato come server Web e configurato con i provider di configurazione dell'app.
    • Aggiungere il middleware di filtro host.
    • Aggiungere il middleware delle intestazioni inoltrate se la variabile di ambiente ASPNETCORE_FORWARDEDHEADERS_ENABLED è impostata su true.
    • Abilitare l'integrazione di IIS.

Altra configurazione

Questo argomento riguarda solo la configurazione dell'app. Altri aspetti dell'esecuzione e dell'hosting delle app ASP.NET Core vengono configurati usando i file di configurazione non descritti in questo argomento:

Variabili di ambiente impostate in launchSettings.json sostituiscono quelle impostate nell'ambiente di sistema.

Per altre informazioni sulla migrazione della configurazione dell'app da versioni precedenti di ASP.NET, vedere Eseguire l'aggiornamento da ASP.NET a ASP.NET Core.

Aggiungere la configurazione da un assembly esterno

Un'implementazione IHostingStartup consente l'aggiunta di miglioramenti a un'app all'avvio, da un assembly esterno alla classe Startup dell'app. Per altre informazioni, vedere Usare assembly di avvio dell'hosting in ASP.NET Core.

Generatore di origini con associazione della configurazione

Il generatore di origine dell'associazione di configurazione fornisce la configurazione AOT e trim-friendly. Per altre informazioni, vedere Generatore di origine dell'associazione di configurazione.

Risorse aggiuntive

La configurazione dell'applicazione in ASP.NET Core viene eseguita usando uno o più provider di configurazione. I provider di configurazione leggono i dati di configurazione da coppie chiave-valore usando diverse origini di configurazione:

  • File di impostazioni, ad esempio appsettings.json
  • Variabili di ambiente
  • Azure Key Vault
  • Configurazione app di Azure
  • Argomenti della riga di comando
  • Provider personalizzati, installati o creati
  • File della directory
  • Oggetti .NET in memoria

Questo articolo offre informazioni sulla configurazione in ASP.NET Core. Per informazioni sull'uso della configurazione nelle app console, vedere Configurazione di .NET.

Configurazione dell'applicazione e dell'host

Le app ASP.NET Core configurano e avviano un host. L'host è responsabile della gestione dell'avvio e della durata delle app. I modelli di ASP.NET Core creano un WebApplicationBuilder che contiene l'host. Sebbene parte della configurazione possa essere eseguita sia nel provider di configurazione dell'host che nel provider di configurazione dell'applicazione, in generale solo la configurazione necessaria all'host deve essere eseguita nella configurazione dell'host.

La configurazione dell'applicazione è la priorità più alta ed è descritta nel dettaglio nella sezione successiva. La configurazione dell'host segue la configurazione dell'applicazione ed è descritta in questo articolo.

Origini della configurazione dell'applicazione predefinite

Le app Web ASP.NET Core create con dotnet new o Visual Studio generano il codice seguente:

var builder = WebApplication.CreateBuilder(args);

WebApplication.CreateBuilder inizializza una nuova istanza della classe WebApplicationBuilder con valori predefiniti preconfigurati. Il WebApplicationBuilder (builder) inizializzato offre la configurazione predefinita per l'app nell'ordine seguente, dalla priorità più alta a quella più bassa:

  1. Argomenti della riga di comando che usano il provider di configurazione della riga di comando.
  2. Variabili di ambiente senza prefisso che usano il provider di configurazione delle variabili di ambiente senza prefisso.
  3. Segreti dell'utente quando l'app viene eseguita nell'ambiente Development.
  4. appsettings.{Environment}.json usando il provider di configurazione JSON. Ad esempio, appsettings.Production.json e appsettings.Development.json.
  5. appsettings.json usando il provider di configurazione JSON.
  6. Un fallback alla configurazione dell'host descritto nella sezione successiva.

Origini della configurazione dell'host predefinite

L'elenco seguente contiene le origini di configurazione host predefinite dalla priorità più alta alla più bassa per WebApplicationBuilder:

  1. Argomenti della riga di comando che usano il provider di configurazione della riga di comando
  2. Variabili di ambiente con prefisso DOTNET_ che usano il provider di configurazione delle variabili di ambiente.
  3. Variabili di ambiente con prefisso ASPNETCORE_ che usano il provider di configurazione delle variabili di ambiente.

Per l'host generico .NET e l'host Web, le origini di configurazione host predefinite dalla priorità più alta alla più bassa sono:

  1. Variabili di ambiente con prefisso ASPNETCORE_ che usano il provider di configurazione delle variabili di ambiente.
  2. Argomenti della riga di comando che usano il provider di configurazione della riga di comando
  3. Variabili di ambiente con prefisso DOTNET_ che usano il provider di configurazione delle variabili di ambiente.

Quando un valore di configurazione viene impostato nella configurazione dell'host e dell'applicazione, viene usata la configurazione dell'applicazione.

Variabili dell'host

Le variabili seguenti vengono bloccate in anticipo durante l'inizializzazione dei generatori di host e non possono essere influenzate dalla configurazione dell'applicazione:

Ogni altra impostazione dell'host viene letta dalla configurazione dell'applicazione anziché dalla configurazione dell'host.

URLS è una delle numerose impostazioni dell'host comuni che non è un'impostazione bootstrap. Come tutte le altre impostazioni dell'host non presenti nell'elenco precedente, URLS viene letta successivamente dalla configurazione dell'applicazione. Poiché la configurazione dell'host è un fallback per la configurazione dell'applicazione, la configurazione dell'host può essere usata per impostare URLS, ma verrà sostituita da qualsiasi origine di configurazione nella configurazione dell'applicazione, come appsettings.json.

Per altre informazioni, vedere Modificare la radice del contenuto, il nome dell'app e l'ambiente e Modificare la radice del contenuto, il nome dell'app e l'ambiente in base alle variabili di ambiente o alla riga di comando

Le sezioni rimanenti di questo articolo fanno riferimento alla configurazione dell'applicazione.

Provider di configurazione dell'applicazione

Il codice seguente visualizza i provider di configurazione abilitati nell'ordine in cui sono stati aggiunti:

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

L'elenco precedente delle origini di configurazione predefinite dalla priorità più alta alla priorità più bassa mostra i provider nell'ordine opposto in cui vengono aggiunti all'applicazione generata dal modello. Ad esempio, il provider di configurazione JSON viene aggiunto prima del provider di configurazione della riga di comando.

I provider di configurazione aggiunti successivamente hanno priorità più alta e sostituiscono le impostazioni delle chiavi precedenti. Ad esempio, se MyKey è impostato sia in appsettings.json che nell'ambiente, viene usato il valore dell'ambiente. Quando si usano i provider di configurazione predefiniti, il provider di configurazione della riga di comando sostituisce tutti gli altri provider.

Per altre informazioni su CreateBuilder, vedere Impostazioni predefinite del generatore.

appsettings.json

Considerare il file appsettings.json seguente:

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

Il codice seguente del download di esempio visualizza diverse impostazioni delle configurazioni precedenti:

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

Il JsonConfigurationProvider predefinito carica la configurazione nell'ordine seguente:

  1. appsettings.json
  2. appsettings.{Environment}.json : ad esempio, i file appsettings.Production.json e appsettings.Development.json. La versione dell'ambiente del file viene caricata in base a IHostingEnvironment.EnvironmentName. Per altre informazioni, vedere Usare più ambienti in ASP.NET Core.

I valori appsettings.{Environment}.json sostituiscono le chiavi in appsettings.json. Ad esempio, per impostazione predefinita:

  • Nello sviluppo la configurazione appsettings.Development.json sovrascrive i valori trovati in appsettings.json.
  • Nella produzione la configurazione appsettings.Production.json sovrascrive i valori trovati in appsettings.json. Ad esempio, durante la distribuzione dell'app in Azure.

Se è necessario garantire un valore di configurazione, vedere GetValue. L'esempio precedente legge solo le stringhe e non supporta un valore predefinito.

Quando si usa la configurazione predefinita, i file appsettings.json e appsettings.{Environment}.json sono abilitati con reloadOnChange: true. Le modifiche apportate al appsettings.json file e appsettings.{Environment}.json dopo l'avvio dell'app vengono lette dal provider di configurazione JSON.

Commenti in appsettings.json

I commenti in appsettings.json e appsettings.{Environment}.jsoni file sono supportati usando commenti in stile JavaScript o C#.

Associare dati di configurazione gerarchici usando il modello di opzioni

Il modo preferito per leggere i valori di configurazione correlati prevede l'uso del modello di opzioni. Ad esempio, per leggere i valori di configurazione seguenti:

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

Creare la classe PositionOptions seguente:

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

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

Una classe di opzioni:

  • Deve essere non astratta con un costruttore pubblico senza parametri.
  • Tutte le proprietà di lettura/scrittura pubbliche del tipo sono associate.
  • I campi non sono associati. Nel codice precedente Position non è associato. Il campo Position viene usato in modo che la stringa "Position" non debba essere hardcoded nell'app quando la classe viene associata a un provider di configurazione.

Il codice seguente:

  • Chiama ConfigurationBinder.Bind per associare la classe PositionOptions alla sezione Position.
  • Visualizza i dati di configurazione di Position.
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}");
    }
}

Nel codice precedente, per impostazione predefinita, le modifiche apportate al file di configurazione JSON dopo l'avvio dell'app vengono lette.

ConfigurationBinder.Get<T> associa e restituisce il tipo specificato. ConfigurationBinder.Get<T> può risultare più utile rispetto all'uso di ConfigurationBinder.Bind. Il codice seguente mostra come usare ConfigurationBinder.Get<T> con la classe PositionOptions:

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

Nel codice precedente, per impostazione predefinita, le modifiche apportate al file di configurazione JSON dopo l'avvio dell'app vengono lette.

Un approccio alternativo quando si usa il modello opzioni consiste nell'associare la sezione Position e aggiungerla al contenitore del servizio di inserimento di dipendenze. Nel codice seguente PositionOptions viene aggiunta al contenitore del servizio con Configure e associata alla configurazione:

using ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

Quando si usa il codice precedente, il codice seguente legge le opzioni di posizione:

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

Nel codice precedente le modifiche al file di configurazione JSON dopo l'avvio dell'app non vengono lette. Per leggere le modifiche dopo l'avvio dell'app, usare IOptionsSnapshot.

Quando si usa la configurazione predefinita, i file appsettings.json e appsettings.{Environment}.json sono abilitati con reloadOnChange: true. Le modifiche apportate al appsettings.json file e appsettings.{Environment}.json dopo l'avvio dell'app vengono lette dal provider di configurazione JSON.

Per informazioni sull'aggiunta di file di configurazione JSON aggiuntivi, vedere Provider di configurazione JSON in questo documento.

Combinazione della raccolta di servizi

Considerare il codice seguente che registra i servizi e configura le opzioni:

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();

I gruppi correlati di registrazioni possono essere spostati in un metodo di estensione per registrare i servizi. Ad esempio, i servizi di configurazione vengono aggiunti alla classe seguente:

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

        public static IServiceCollection AddMyDependencyGroup(
             this IServiceCollection services)
        {
            services.AddScoped<IMyDependency, MyDependency>();
            services.AddScoped<IMyDependency2, MyDependency2>();

            return services;
        }
    }
}

I servizi rimanenti vengono registrati in una classe simile. Il codice seguente usa i nuovi metodi di estensione per registrare i servizi:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

Nota: ogni metodo di estensione services.Add{GROUP_NAME} aggiunge e configura potenzialmente i servizi. Ad esempio, AddControllersWithViews aggiunge i controller MVC dei servizi con visualizzazioni richiesti e AddRazorPages aggiunge le pagina Razor dei servizi richieste.

Sicurezza e segreti dell'utente

Linee guida per i dati di configurazione:

  • Non archiviare mai la password o altri dati sensibili nel codice del provider di configurazione o in file di configurazione di testo normale. Per l'archiviazione di segreti per lo sviluppo, è possibile usare lo strumento Secret Manager.
  • Non usare i segreti di produzione in ambienti di sviluppo o di test.
  • Specificare i segreti all'esterno del progetto in modo che non possano essere inavvertitamente inviati a un repository del codice sorgente.
  • Le app di produzione devono usare il flusso di autenticazione più sicuro disponibile. Per altre informazioni, vedere Proteggere i flussi di autenticazione.

Per impostazione predefinita, l'origine di configurazione dei segreti utente viene registrata dopo le origini di configurazione JSON. Pertanto, le chiavi dei segreti dell'utente hanno la precedenza sulle chiavi in appsettings.json e appsettings.{Environment}.json.

Per altre informazioni sull'archiviazione di password o altri dati sensibili:

Azure Key Vault archivia in modo sicuro i segreti delle app ASP.NET Core. Per altre informazioni, vedere Provider di configurazione di Azure Key Vault in ASP.NET Core.

Variabili di ambiente senza prefisso

Le variabili di ambiente senza prefisso sono variabili di ambiente diverse da quelle precedute da ASPNETCORE_ o DOTNET_. Ad esempio, i modelli di applicazione Web ASP.NET Core impostano "ASPNETCORE_ENVIRONMENT": "Development" in launchSettings.json. Per altre informazioni sulle variabili di ambiente ASPNETCORE_ e DOTNET_, vedere:

Quando si usa la configurazione predefinita, EnvironmentVariablesConfigurationProvider carica la configurazione dalle coppie chiave-valore delle variabili di ambiente dopo la lettura di appsettings.json, appsettings.{Environment}.json e dei segreti dell'utente. Therefore, i valori di chiave letti dall'ambiente sostituiscono i valori letti da appsettings.json, appsettings.{Environment}.json e dai segreti dell'utente.

Il separatore : non funziona con le chiavi gerarchiche delle variabili di ambiente in tutte le piattaforme. Ad esempio, il : separatore non è supportato da Bash. Il doppio carattere di sottolineatura, __, è:

  • Supportato da tutte le piattaforme.
  • Sostituito automaticamente da due punti, :.

I comandi set seguenti:

  • Impostano le chiavi e i valori di ambiente dell'esempio precedente in Windows.
  • Testano le impostazioni quando viene usato il download di esempio. Il comando dotnet run deve essere eseguito nella directory del progetto.
set MyKey="My key from Environment"
set Position__Title=Environment_Editor
set Position__Name=Environment_Rick
dotnet run

Le impostazioni dell'ambiente precedenti:

  • Sono impostate solo nei processi avviati dalla finestra di comando in cui sono stati impostate.
  • Non verranno lette dai browser avviati con Visual Studio.

I comandi setx seguenti possono essere usati per impostare le chiavi e i valori di ambiente in Windows. A differenza di set, le impostazioni setx vengono mantenute. /M imposta la variabile nell'ambiente di sistema. Se non viene usata l'opzione /M, viene impostata una variabile di ambiente dell'utente.

setx MyKey "My key from setx Environment" /M
setx Position__Title Environment_Editor /M
setx Position__Name Environment_Rick /M

Per verificare che i comandi precedenti sostituiscano appsettings.json e appsettings.{Environment}.json:

  • Con Visual Studio: uscire e riavviare Visual Studio.
  • Con l'interfaccia della riga di comando: avviare una nuova finestra di comando e immettere dotnet run.

Chiamare AddEnvironmentVariables con una stringa per specificare un prefisso per le variabili di ambiente:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

Nel codice precedente:

Il prefisso viene rimosso quando vengono lette le coppie chiave-valore della configurazione.

I comandi seguenti testano il prefisso personalizzato:

set MyCustomPrefix_MyKey="My key with MyCustomPrefix_ Environment"
set MyCustomPrefix_Position__Title=Editor_with_customPrefix
set MyCustomPrefix_Position__Name=Environment_Rick_cp
dotnet run

La configurazione predefinita carica le variabili di ambiente e gli argomenti della riga di comando con prefisso DOTNET_ e ASPNETCORE_. I prefissi DOTNET_ e ASPNETCORE_ vengono usati da ASP.NET Core per la configurazione dell'host e dell'app, ma non per la configurazione dell'utente. Per altre informazioni sulla configurazione dell'host e dell'app, vedere Host generico .NET.

In Servizio app di Azure selezionare Nuova impostazione applicazione nella pagina Impostazioni > Configurazione. Le impostazioni applicazione del Servizio app di Azure sono:

  • Crittografato in e rest trasmesso tramite un canale crittografato.
  • Esposte come variabili di ambiente.

Per altre informazioni, vedere App di Azure: Eseguire l'override della configurazione delle app usando il portale di Azure.

Per informazioni sulle stringhe di connessione del database di Azure, vedere Prefissi della stringa di connessione.

Denominazione delle variabili di ambiente

I nomi delle variabili di ambiente riflettono la struttura di un file appsettings.json. Ogni elemento nella gerarchia è separato da un doppio carattere di sottolineatura (preferibile) o due punti. Quando la struttura dell'elemento include una matrice, l'indice della matrice deve essere considerato come un nome di elemento aggiuntivo in questo percorso. Si consideri il file appsettings.json seguente e i relativi valori equivalenti rappresentati come variabili di ambiente.

appsettings.json

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

variabili di ambiente

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

Variabili di ambiente impostate nel file launchSettings.json generato

Variabili di ambiente impostate in launchSettings.json sostituiscono quelle impostate nell'ambiente di sistema. Ad esempio, i modelli Web ASP.NET Core generano un file launchSettings.json che imposta la configurazione dell'endpoint su:

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

La configurazione di applicationUrl imposta la variabile di ambiente ASPNETCORE_URLS e sostituisce i valori impostati nell'ambiente.

Carattere di escape per le variabili di ambiente in Linux

In Linux il valore delle variabili di ambiente degli URL deve essere preceduto da un carattere di escape in modo che systemd possa analizzarle. Usare lo strumento linux systemd-escape che restituisce http:--localhost:5001

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

Visualizzare le variabili di ambiente

Il codice seguente visualizza le variabili di ambiente e i valori all'avvio dell'applicazione, utile durante il debug delle impostazioni di ambiente:

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

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

Riga di comando

Quando si usa la configurazione predefinita, CommandLineConfigurationProvider carica la configurazione dalle coppie chiave-valore degli argomenti della riga di comando dopo le origini di configurazione seguenti:

  • File appsettings.json e appsettings.{Environment}.json.
  • Segreti dell'app nell'ambiente di sviluppo.
  • variabili di ambiente.

Per impostazione predefinita, i valori di configurazione impostati nella riga di comando sostituiscono i valori di configurazione impostati con tutti gli altri provider di configurazione.

Argomenti della riga di comando

Il comando seguente imposta chiavi e valori usando =:

dotnet run MyKey="Using =" Position:Title=Cmd Position:Name=Cmd_Rick

Il comando seguente imposta chiavi e valori usando /:

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

Il comando seguente imposta chiavi e valori usando --:

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

Il valore di chiave:

  • Deve seguire = o la chiave deve avere un prefisso -- o / quando il valore segue uno spazio.
  • Non è richiesto se viene usato =. Ad esempio: MySetting=.

Nello stesso comando, non mischiare coppie chiave-valore di argomenti della riga di comando che usano = con coppie chiave-valore che usano uno spazio.

Mapping di sostituzione

I mapping di sostituzione consentono di usare la logica di sostituzione del nome della chiave. Specificare un dizionario delle sostituzioni al metodo AddCommandLine.

Quando viene utilizzato il dizionario dei mapping di sostituzione, nel dizionario viene controllata la presenza di una chiave corrispondente alla chiave fornita da un argomento della riga di comando. Se la chiave della riga di comando viene trovata nel dizionario, il valore del dizionario viene passato nuovamente per impostare la coppia chiave-valore nella configurazione dell'app. Un mapping di sostituzione è necessario per le chiavi della riga di comando con un trattino singolo (-) come prefisso.

Regole principali del dizionario dei mapping di sostituzione:

  • Le sostituzioni devono iniziare con - o --.
  • Il dizionario dei mapping di sostituzione non deve contenere chiavi duplicate.

Per usare un dizionario dei mapping di sostituzione, passarlo nella chiamata a AddCommandLine:


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();

Per testare la sostituzione delle chiavi è possibile eseguire il comando seguente:

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

Il codice seguente mostra i valori di chiave per le chiavi sostituite:

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"]}'");
    }
}

Per le app che usano i mapping di sostituzione, la chiamata a CreateDefaultBuilder non deve passare argomenti. La chiamata AddCommandLine del metodo CreateDefaultBuilder non include sostituzioni mappate e non è possibile passare il dizionario dei mapping di sostituzione a CreateDefaultBuilder. La soluzione non consiste nel passare gli argomenti a CreateDefaultBuilder ma nel consentire al metodo AddCommandLine del metodo ConfigurationBuilder di elaborare entrambi gli argomenti e il dizionario dei mapping di sostituzione.

Impostare gli argomenti dell'ambiente e della riga di comando con Visual Studio

Gli argomenti dell'ambiente e della riga di comando possono essere impostati in Visual Studio dalla finestra dei profili di avvio:

  • In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e selezionare Proprietà.
  • Selezionare la scheda Debug > Generale e selezionare Aprire interfaccia utente profili di avvio debug.

Dati di configurazione gerarchici

L'API di configurazione legge i dati di configurazione gerarchici rendendoli flat grazie all'uso di un delimitatore nelle chiavi di configurazione.

Il download di esempio contiene il file appsettings.json seguente:

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

Il codice seguente del download di esempio visualizza diverse impostazioni delle configurazioni:

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

Il modo preferito per leggere i dati di configurazione gerarchici prevede l'uso del modello di opzioni. Per altre informazioni, vedere Associare dati di configurazione gerarchici in questo documento.

I metodi GetSection e GetChildren sono disponibili per isolare le sezioni e gli elementi figlio di una sezione nei dati di configurazione. Questi metodi sono descritti più avanti in GetSection, GetChildren ed Exists.

Chiavi e valori di configurazione

Avviso

Questo articolo illustra l'uso di stringa di connessione. Con un database locale l'utente non deve essere autenticato, ma nell'ambiente di produzione stringa di connessione talvolta include una password per l'autenticazione. Una credenziale della password del proprietario della risorsa (ROPC) è un rischio per la sicurezza che deve essere evitato nei database di produzione. Le app di produzione devono usare il flusso di autenticazione più sicuro disponibile. Per altre informazioni sull'autenticazione per le app distribuite in ambienti di test o di produzione, vedere Proteggere i flussi di autenticazione.

Chiavi di configurazione:

  • non viene fatta distinzione tra maiuscole e minuscole. Ad esempio, ConnectionString e connectionstring vengono considerate chiavi equivalenti.
  • Se una chiave e un valore sono impostati in più provider di configurazione, viene usato il valore dell'ultimo provider aggiunto. Per altre informazioni, vedere Configurazione predefinita.
  • Chiavi gerarchica
    • Nell'ambito dell'API di configurazione, il separatore due punti (:) funziona in tutte le piattaforme.
    • Nelle variabili di ambiente, un separatore due punti potrebbe non funzionare in tutte le piattaforme. Il doppio carattere di sottolineatura, __, è supportato da tutte le piattaforme e viene convertito automaticamente nei due punti :.
    • In Azure Key Vault le chiavi gerarchiche usano -- come separatore. Il provider di configurazione di Azure Key Vault sostituisce automaticamente -- con : quando i segreti vengono caricati nella configurazione dell'app.
  • Il ConfigurationBinder supporta l'associazione di matrici agli oggetti usando gli indici delle matrici nelle chiavi di configurazione. L'associazione di matrici è descritta nella sezione Associare una matrice a una classe.

Valori di configurazione:

  • sono stringhe.
  • I valori null non possono essere archiviati nella configurazione o associati a oggetti.

Provider di configurazione

La tabella seguente mostra i provider di configurazione disponibili per le app ASP.NET Core.

Provider Fornisce la configurazione da
Azure Key Vault configuration provider (Provider di configurazione di Azure Key Vault) Azure Key Vault
Provider di configurazione app di Azure Configurazione app di Azure
Provider di configurazione della riga di comando Parametri della riga di comando
Provider di configurazione personalizzato Origine personalizzata
Provider di configurazione delle variabili di ambiente Variabili di ambiente
Provider di configurazione file File INI, JSON e XML
Provider di configurazione chiave-per-file File della directory
Provider di configurazione della memoria Raccolte in memoria
Segreti utente File nella directory dei profili utente

Le origini di configurazione vengono lette nell'ordine in cui vengono specificati i rispetti provider di configurazione. Ordinare i provider di configurazione nel codice in base alle priorità per le origini di configurazione sottostanti richieste dall'app.

Una sequenza tipica di provider di configurazione è:

  1. appsettings.json
  2. appsettings.{Environment}.json
  3. Segreti utente
  4. Variabili di ambiente che usano il provider di configurazione delle variabili di ambiente.
  5. Argomenti della riga di comando che usano il provider di configurazione della riga di comando.

È pratica comune aggiungere il provider di configurazione della riga di comando per ultimo in una serie di provider per consentire agli argomenti della riga di comando di sostituire la configurazione impostata da altri provider.

La sequenza di provider precedente è usata nella configurazione predefinita.

Prefissi della stringa di connessione

Avviso

Questo articolo illustra l'uso di stringa di connessione. Con un database locale l'utente non deve essere autenticato, ma nell'ambiente di produzione stringa di connessione talvolta include una password per l'autenticazione. Una credenziale della password del proprietario della risorsa (ROPC) è un rischio per la sicurezza che deve essere evitato nei database di produzione. Le app di produzione devono usare il flusso di autenticazione più sicuro disponibile. Per altre informazioni sull'autenticazione per le app distribuite in ambienti di test o di produzione, vedere Proteggere i flussi di autenticazione.

L'API di configurazione ha regole di elaborazione speciali per quattro variabili di ambiente della stringa di connessione. Queste stringhe di connessione sono coinvolte nella configurazione delle stringhe di connessione di Azure per l'ambiente dell'app. Le variabili di ambiente con i prefissi indicati nella tabella vengono caricate nell'app con la configurazione predefinita o quando non viene specificato alcun prefisso per AddEnvironmentVariables.

Prefisso della stringa di connessione Provider
CUSTOMCONNSTR_ Provider personalizzato
MYSQLCONNSTR_ MySQL
SQLAZURECONNSTR_ Database SQL di Azure
SQLCONNSTR_ SQL Server

Quando una variabile di ambiente viene individuata e caricata nella configurazione con uno qualsiasi dei quattro prefissi indicati nella tabella:

  • La chiave di configurazione viene creata rimuovendo il prefisso della variabile di ambiente e aggiungendo una sezione per la chiave di configurazione (ConnectionStrings).
  • Viene creata una nuova coppia chiave-valore della configurazione che rappresenta il provider di connessione al database (ad eccezione di CUSTOMCONNSTR_, che non ha un provider dichiarato).
Chiave della variabile di ambiente Chiave di configurazione convertita Voce di configurazione del provider
CUSTOMCONNSTR_{KEY} ConnectionStrings:{KEY} Voce di configurazione non creata.
MYSQLCONNSTR_{KEY} ConnectionStrings:{KEY} Chiave: ConnectionStrings:{KEY}_ProviderName:
Valore: MySql.Data.MySqlClient
SQLAZURECONNSTR_{KEY} ConnectionStrings:{KEY} Chiave: ConnectionStrings:{KEY}_ProviderName:
Valore: System.Data.SqlClient
SQLCONNSTR_{KEY} ConnectionStrings:{KEY} Chiave: ConnectionStrings:{KEY}_ProviderName:
Valore: System.Data.SqlClient

Provider di configurazione file

FileConfigurationProvider è la classe base per il caricamento della configurazione dal file system. I provider di configurazione seguenti derivano da FileConfigurationProvider:

Provider di configurazione INI

IniConfigurationProvider carica la configurazione da coppie chiave-valore di file INI in fase di esecuzione.

Il codice seguente aggiunge diversi provider di configurazione:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddIniFile("MyIniConfig.ini", optional: true, reloadOnChange: true)
    .AddIniFile($"MyIniConfig.{builder.Environment.EnvironmentName}.ini",
                optional: true, reloadOnChange: true);

builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

Nel codice precedente le impostazioni nei file MyIniConfig.ini e MyIniConfig.{Environment}.ini sono sostituite dalle impostazioni in:

Il download di esempio contiene il file MyIniConfig.ini seguente:

MyKey="MyIniConfig.ini Value"

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

[Logging:LogLevel]
Default=Information
Microsoft=Warning

Il codice seguente del download di esempio visualizza diverse impostazioni delle configurazioni precedenti:

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

Provider di configurazione JSON

Carica JsonConfigurationProvider la configurazione dalle coppie chiave-valore del file JSON.

Gli overload possono specificare:

  • Se il file è facoltativo.
  • Se la configurazione viene ricaricata se viene modificato il file.

Osservare il codice seguente:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddJsonFile("MyConfig.json",
        optional: true,
        reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

Il codice precedente:

In genere non si vuole che un file JSON personalizzato sostituisci i valori impostati nel provider di configurazione delle variabili di ambiente e nel provider di configurazione della riga di comando.

Provider di configurazione XML

Il XmlConfigurationProvider carica la configurazione da coppie chiave-valore di file XML in fase di esecuzione.

Il codice seguente aggiunge diversi provider di configurazione:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddXmlFile("MyXMLFile.xml", optional: true, reloadOnChange: true)
    .AddXmlFile($"MyXMLFile.{builder.Environment.EnvironmentName}.xml",
                optional: true, reloadOnChange: true);

builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

Nel codice precedente le impostazioni nei file MyXMLFile.xml e MyXMLFile.{Environment}.xml sono sostituite dalle impostazioni in:

Il download di esempio contiene il file MyXMLFile.xml seguente:

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

Il codice seguente del download di esempio visualizza diverse impostazioni delle configurazioni precedenti:

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

La ripetizione di elementi che usano lo stesso nome di elemento funziona se si usa l'attributo name per distinguere gli elementi:

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

Il codice seguente legge il file di configurazione precedente e visualizza le chiavi e i valori:

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

È possibile usare attributi per fornire valori:

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

Il file di configurazione precedente carica le chiavi seguenti con value:

  • key:attribute
  • section:key:attribute

Provider di configurazione chiave-per-file

Il KeyPerFileConfigurationProvider usa i file di una directory come coppie chiave-valore della configurazione. La chiave è il nome del file. Il valore contiene il contenuto del file. Il provider di configurazione chiave-per-file viene usato negli scenari di hosting di Docker.

Per attivare la configurazione chiave-per-file, chiamare il metodo di estensione AddKeyPerFile su un'istanza di ConfigurationBuilder. Il directoryPath per i file deve essere un percorso assoluto.

Gli overload consentono di specificare:

  • Un delegato Action<KeyPerFileConfigurationSource> che configura l'origine.
  • Se la directory è facoltativa e il percorso della directory.

Il doppio carattere di sottolineatura (__) viene usato come delimitatore per le chiavi di configurazione nei nomi dei file. Ad esempio, il nome di file Logging__LogLevel__System produce la chiave di configurazione Logging:LogLevel:System.

Chiamare ConfigureAppConfiguration quando si crea l'host per specificare la configurazione dell'app:

.ConfigureAppConfiguration((hostingContext, config) =>
{
    var path = Path.Combine(
        Directory.GetCurrentDirectory(), "path/to/files");
    config.AddKeyPerFile(directoryPath: path, optional: true);
})

Provider di configurazione della memoria

Il MemoryConfigurationProvider usa una raccolta in memoria come coppie chiave-valore della configurazione.

Il codice seguente aggiunge una raccolta di memoria al sistema di configurazione:

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.Configuration.AddInMemoryCollection(Dict);
builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

Il codice seguente del download di esempio visualizza le impostazioni delle configurazioni precedenti:

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

Nel codice precedente config.AddInMemoryCollection(Dict) viene aggiunto dopo i provider di configurazione predefiniti. Per un esempio di ordinamento dei provider di configurazione, vedere Provider di configurazione JSON.

Vedere Associare una matrice per un altro esempio che usa MemoryConfigurationProvider.

Configurazione di endpoint Kestrel

La configurazione di endpoint specifica di Kestrel sostituisce tutte le configurazioni di endpoint tra server. Le configurazioni di endpoint tra server includono:

Si consideri il file appsettings.json seguente usato in un'app Web ASP.NET Core:

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

Quando il markup evidenziato precedente viene usato in un'app Web ASP.NET Core e l'app viene avviata dalla riga di comando con la configurazione dell'endpoint tra server seguente:

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

Kestrel si associa all'endpoint configurato specificatamente per Kestrel nel file appsettings.json (https://localhost:9999) e non in https://localhost:7777.

Si consideri l'endpoint specifico di Kestrel configurato come variabile di ambiente:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

nella variabile di ambiente precedente Https è il nome dell'endpoint specifico di Kestrel. Il file appsettings.json precedente definisce anche un endpoint specifico di Kestrel denominato Https. Per impostazione predefinita, le variabili di ambiente che usano il provider di configurazione delle variabili di ambiente vengono lette dopo appsettings.{Environment}.json, di conseguenza la variabile di ambiente precedente viene usata per l'endpoint Https.

GetValue

ConfigurationBinder.GetValue estrae un valore dalla configurazione con una chiave specificata e lo converte nel tipo specificato:

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

Nel codice precedente, se NumberKey non viene trovato nella configurazione, viene usato il valore predefinito di 99.

GetSection, GetChildren ed Exists

Per gli esempi che seguono, prendere in considerazione il file MySubsection.json seguente:

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

Il codice seguente aggiunge MySubsection.json ai provider di configurazione:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddJsonFile("MySubsection.json",
                 optional: true,
                 reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

GetSection

IConfiguration.GetSection restituisce una sottosezione della configurazione con la chiave di sottosezione specificata.

Il codice seguente restituisce i valori per section1:

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"]}'");
    }
}

Il codice seguente restituisce i valori per section2:subsection0:

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 non restituisce mai null. Se non viene trovata una sezione corrispondente, viene restituita una IConfigurationSection vuota.

Quando GetSection restituisce una sezione corrispondente, Value non viene compilata. Quando la sezione esiste, vengono restituiti Key e Path.

GetChildren ed Exists

Il codice seguente chiama IConfiguration.GetChildren e restituisce i valori per section2:subsection0:

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

Il codice precedente chiama ConfigurationExtensions.Exists per verificare che la sezione esista:

Associare una matrice

Il ConfigurationBinder.Bind supporta l'associazione di matrici agli oggetti usando gli indici delle matrici nelle chiavi di configurazione. Qualsiasi formato di matrice che espone un segmento chiave numerico supporta l'associazione di matrici a una matrice di classi POCO.

Si consideri MyArray.json del download di esempio:

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

Il codice seguente aggiunge MyArray.json ai provider di configurazione:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddJsonFile("MyArray.json",
                 optional: true,
                 reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

Il codice seguente legge la configurazione e visualizza i valori:

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>();
        if (_array == null)
        {
            throw new ArgumentNullException(nameof(_array));
        }
        string s = String.Empty;

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

        return Content(s);
    }
}
public class ArrayExample
{
    public string[]? Entries { get; set; } 
}

Il codice precedente restituisce l'output seguente:

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

Nell'output precedente Index 3 ha il valore value40, corrispondente a "4": "value40", in MyArray.json. Gli indici di matrice associati sono continui e non associati all'indice delle chiavi di configurazione. Il binder di configurazione non supporta l'associazione di valori Null o la creazione di voci Null negli oggetti associati.

Provider di configurazione personalizzato

L'app di esempio dimostra come creare un provider di configurazione di base che legge le coppie chiave-valore di configurazione da un database usando Entity Framework (EF).

Il provider ha le caratteristiche seguenti:

  • Il database in memoria di Entity Framework viene usato a scopo dimostrativo. Per usare un database che richiede una stringa di connessione, implementare un ConfigurationBuilder secondario per fornire la stringa di connessione da un altro provider di configurazione.
  • Il provider legge una tabella di database in una configurazione all'avvio. Il provider non esegue una query sul database per ogni chiave.
  • Il ricaricamento in caso di modifica non è implementato, quindi l'aggiornamento del database dopo l'avvio dell'app non ha alcun effetto sulla configurazione dell'app.

Definire un'entità EFConfigurationValue per l'archiviazione dei valori di configurazione nel database.

Models/EFConfigurationValue.cs:

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

Aggiungere EFConfigurationContext per archiviare i valori configurati e accedervi.

EFConfigurationProvider/EFConfigurationContext.cs:

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

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

Creare una classe che implementi IConfigurationSource.

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

Creare il provider di configurazione personalizzato ereditando da ConfigurationProvider. Il provider di configurazione inizializza il database quando è vuoto. Poiché nelle chiavi di configurazione non viene fatta distinzione tra maiuscole e minuscole, il dizionario usato per inizializzare il database viene creato con l'operatore di confronto senza distinzione tra maiuscole e minuscole (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-2005
        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;
    }
}

Un metodo di estensione AddEFConfiguration consente di aggiungere l'origine di configurazione a un ConfigurationBuilder.

Extensions/EntityFrameworkExtensions.cs:

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

Il codice seguente mostra come usare EFConfigurationProvider personalizzato in Program.cs:

//using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

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

var app = builder.Build();

app.Run();

Configurazione dell'accesso con inserimento delle dipendenze

La configurazione può essere inserita nei servizi usando l'inserimento delle dipendenze attraverso la risoluzione del servizio IConfiguration:

public class Service
{
    private readonly IConfiguration _config;

    public Service(IConfiguration config) =>
        _config = config;

    public void DoSomething()
    {
        var configSettingValue = _config["ConfigSetting"];

        // ...
    }
}

Per informazioni su come accedere ai valori usando IConfiguration, vedere GetValue e GetSection, GetChildren ed Exists in questo articolo.

Accedere alla configurazione nelle pagine Razor

Il codice seguente visualizza i dati di configurazione in una pagina Razor:

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

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

Nel codice seguente MyOptions viene aggiunta al contenitore del servizio con Configure e associata alla configurazione:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

Il markup seguente usa la direttiva @injectRazor per risolvere e visualizzare i valori delle opzioni:

@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>

Accedere alla configurazione in un file di visualizzazione MVC

Il codice seguente visualizza i dati di configurazione in una visualizzazione MVC:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

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

Accedere alla configurazione in Program.cs

Il codice seguente accede alla configurazione nel file Program.cs.

var builder = WebApplication.CreateBuilder(args);

var key1 = builder.Configuration.GetValue<string>("KeyOne");

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

var key2 = app.Configuration.GetValue<int>("KeyTwo");
var key3 = app.Configuration.GetValue<bool>("KeyThree");

app.Logger.LogInformation("KeyOne: {KeyOne}", key1);
app.Logger.LogInformation("KeyTwo: {KeyTwo}", key2);
app.Logger.LogInformation("KeyThree: {KeyThree}", key3);

app.Run();

In appsettings.json per l'esempio precedente:

{
  ...
  "KeyOne": "Key One Value",
  "KeyTwo": 1999,
  "KeyThree": true
}

Configurare opzioni con un delegato

Le opzioni configurate in un delegato sostituiscono i valori impostati nei provider di configurazione.

Nel codice seguente viene aggiunto un servizio IConfigureOptions<TOptions> al contenitore di servizi. Viene usato un delegato per configurare i valori per MyOptions:

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();

Il codice seguente visualizza i valori delle opzioni:

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

Nell'esempio precedente i valori di Option1 e Option2 sono specificati in appsettings.json e quindi sostituiti dal delegato configurato.

Host e configurazione delle app

Prima che l'app venga configurata e avviata, viene configurato e avviato un host. L'host è responsabile della gestione dell'avvio e della durata delle app. Sia l'app che l'host vengono configurati tramite i provider di configurazione descritti in questo argomento. Anche le coppie chiave-valore di configurazione dell'host sono incluse nella configurazione dell'app. Per altre informazioni su come vengono usati i provider di configurazione per la creazione dell'host e sugli effetti delle origini di configurazione sulla configurazione dell'host, vedere Panoramica delle nozioni di base su ASP.NET Core.

Configurazione dell'host predefinita

Per informazioni dettagliate sulla configurazione predefinita quando viene usato l'host Web, vedere la versione di questo argomento per ASP.NET Core 2.2.

  • La configurazione dell'host viene fornita da:
  • Viene stabilita la configurazione predefinita dell'host Web (ConfigureWebHostDefaults):
    • Kestrel viene usato come server Web e configurato con i provider di configurazione dell'app.
    • Aggiungere il middleware di filtro host.
    • Aggiungere il middleware delle intestazioni inoltrate se la variabile di ambiente ASPNETCORE_FORWARDEDHEADERS_ENABLED è impostata su true.
    • Abilitare l'integrazione di IIS.

Altra configurazione

Questo argomento riguarda solo la configurazione dell'app. Altri aspetti dell'esecuzione e dell'hosting delle app ASP.NET Core vengono configurati usando i file di configurazione non descritti in questo argomento:

Variabili di ambiente impostate in launchSettings.json sostituiscono quelle impostate nell'ambiente di sistema.

Per altre informazioni sulla migrazione della configurazione dell'app da versioni precedenti di ASP.NET, vedere Eseguire l'aggiornamento da ASP.NET a ASP.NET Core.

Aggiungere la configurazione da un assembly esterno

Un'implementazione IHostingStartup consente l'aggiunta di miglioramenti a un'app all'avvio, da un assembly esterno alla classe Startup dell'app. Per altre informazioni, vedere Usare assembly di avvio dell'hosting in ASP.NET Core.

Risorse aggiuntive

La configurazione dell'applicazione in ASP.NET Core viene eseguita usando uno o più provider di configurazione. I provider di configurazione leggono i dati di configurazione da coppie chiave-valore usando diverse origini di configurazione:

  • File di impostazioni, ad esempio appsettings.json
  • Variabili di ambiente
  • Azure Key Vault
  • Configurazione app di Azure
  • Argomenti della riga di comando
  • Provider personalizzati, installati o creati
  • File della directory
  • Oggetti .NET in memoria

Questo articolo offre informazioni sulla configurazione in ASP.NET Core. Per informazioni sull'uso della configurazione nelle app console, vedere Configurazione di .NET.

Configurazione dell'applicazione e dell'host

Le app ASP.NET Core configurano e avviano un host. L'host è responsabile della gestione dell'avvio e della durata delle app. I modelli di ASP.NET Core creano un WebApplicationBuilder che contiene l'host. Sebbene parte della configurazione possa essere eseguita sia nel provider di configurazione dell'host che nel provider di configurazione dell'applicazione, in generale solo la configurazione necessaria all'host deve essere eseguita nella configurazione dell'host.

La configurazione dell'applicazione è la priorità più alta ed è descritta nel dettaglio nella sezione successiva. La configurazione dell'host segue la configurazione dell'applicazione ed è descritta in questo articolo.

Origini della configurazione dell'applicazione predefinite

Le app Web ASP.NET Core create con dotnet new o Visual Studio generano il codice seguente:

var builder = WebApplication.CreateBuilder(args);

WebApplication.CreateBuilder inizializza una nuova istanza della classe WebApplicationBuilder con valori predefiniti preconfigurati. Il WebApplicationBuilder (builder) inizializzato offre la configurazione predefinita per l'app nell'ordine seguente, dalla priorità più alta a quella più bassa:

  1. Argomenti della riga di comando che usano il provider di configurazione della riga di comando.
  2. Variabili di ambiente senza prefisso che usano il provider di configurazione delle variabili di ambiente senza prefisso.
  3. Segreti dell'utente quando l'app viene eseguita nell'ambiente Development.
  4. appsettings.{Environment}.json usando il provider di configurazione JSON. Ad esempio, appsettings.Production.json e appsettings.Development.json.
  5. appsettings.json usando il provider di configurazione JSON.
  6. Un fallback alla configurazione dell'host descritto nella sezione successiva.

Origini della configurazione dell'host predefinite

L'elenco seguente contiene le origini della configurazione dell'host predefinite, dalla priorità più alta a quella più bassa:

  1. Variabili di ambiente con prefisso ASPNETCORE_ che usano il provider di configurazione delle variabili di ambiente.
  2. Argomenti della riga di comando che usano il provider di configurazione della riga di comando
  3. Variabili di ambiente con prefisso DOTNET_ che usano il provider di configurazione delle variabili di ambiente.

Quando un valore di configurazione viene impostato nella configurazione dell'host e dell'applicazione, viene usata la configurazione dell'applicazione.

Vedere Spiegazione in questo commento di GitHub per una spiegazione del perché nella configurazione dell'host, le variabili di ambiente con prefisso ASPNETCORE_ hanno una priorità più alta degli argomenti della riga di comando.

Variabili dell'host

Le variabili seguenti vengono bloccate in anticipo durante l'inizializzazione dei generatori di host e non possono essere influenzate dalla configurazione dell'applicazione:

Ogni altra impostazione dell'host viene letta dalla configurazione dell'applicazione anziché dalla configurazione dell'host.

URLS è una delle numerose impostazioni dell'host comuni che non è un'impostazione bootstrap. Come tutte le altre impostazioni dell'host non presenti nell'elenco precedente, URLS viene letta successivamente dalla configurazione dell'applicazione. Poiché la configurazione dell'host è un fallback per la configurazione dell'applicazione, la configurazione dell'host può essere usata per impostare URLS, ma verrà sostituita da qualsiasi origine di configurazione nella configurazione dell'applicazione, come appsettings.json.

Per altre informazioni, vedere Modificare la radice del contenuto, il nome dell'app e l'ambiente e Modificare la radice del contenuto, il nome dell'app e l'ambiente in base alle variabili di ambiente o alla riga di comando

Le sezioni rimanenti di questo articolo fanno riferimento alla configurazione dell'applicazione.

Provider di configurazione dell'applicazione

Il codice seguente visualizza i provider di configurazione abilitati nell'ordine in cui sono stati aggiunti:

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

L'elenco precedente delle origini di configurazione predefinite dalla priorità più alta alla priorità più bassa mostra i provider nell'ordine opposto in cui vengono aggiunti all'applicazione generata dal modello. Ad esempio, il provider di configurazione JSON viene aggiunto prima del provider di configurazione della riga di comando.

I provider di configurazione aggiunti successivamente hanno priorità più alta e sostituiscono le impostazioni delle chiavi precedenti. Ad esempio, se MyKey è impostato sia in appsettings.json che nell'ambiente, viene usato il valore dell'ambiente. Quando si usano i provider di configurazione predefiniti, il provider di configurazione della riga di comando sostituisce tutti gli altri provider.

Per altre informazioni su CreateBuilder, vedere Impostazioni predefinite del generatore.

appsettings.json

Considerare il file appsettings.json seguente:

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

Il codice seguente del download di esempio visualizza diverse impostazioni delle configurazioni precedenti:

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

Il JsonConfigurationProvider predefinito carica la configurazione nell'ordine seguente:

  1. appsettings.json
  2. appsettings.{Environment}.json : ad esempio, i file appsettings.Production.json e appsettings.Development.json. La versione dell'ambiente del file viene caricata in base a IHostingEnvironment.EnvironmentName. Per altre informazioni, vedere Usare più ambienti in ASP.NET Core.

I valori appsettings.{Environment}.json sostituiscono le chiavi in appsettings.json. Ad esempio, per impostazione predefinita:

  • Nello sviluppo la configurazione appsettings.Development.json sovrascrive i valori trovati in appsettings.json.
  • Nella produzione la configurazione appsettings.Production.json sovrascrive i valori trovati in appsettings.json. Ad esempio, durante la distribuzione dell'app in Azure.

Se è necessario garantire un valore di configurazione, vedere GetValue. L'esempio precedente legge solo le stringhe e non supporta un valore predefinito.

Quando si usa la configurazione predefinita, i file appsettings.json e appsettings.{Environment}.json sono abilitati con reloadOnChange: true. Le modifiche apportate al appsettings.json file e appsettings.{Environment}.json dopo l'avvio dell'app vengono lette dal provider di configurazione JSON.

Associare dati di configurazione gerarchici usando il modello di opzioni

Il modo preferito per leggere i valori di configurazione correlati prevede l'uso del modello di opzioni. Ad esempio, per leggere i valori di configurazione seguenti:

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

Creare la classe PositionOptions seguente:

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

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

Una classe di opzioni:

  • Deve essere non astratta con un costruttore pubblico senza parametri.
  • Tutte le proprietà di lettura/scrittura pubbliche del tipo sono associate.
  • I campi non sono associati. Nel codice precedente Position non è associato. Il campo Position viene usato in modo che la stringa "Position" non debba essere hardcoded nell'app quando la classe viene associata a un provider di configurazione.

Il codice seguente:

  • Chiama ConfigurationBinder.Bind per associare la classe PositionOptions alla sezione Position.
  • Visualizza i dati di configurazione di Position.
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}");
    }
}

Nel codice precedente, per impostazione predefinita, le modifiche apportate al file di configurazione JSON dopo l'avvio dell'app vengono lette.

ConfigurationBinder.Get<T> associa e restituisce il tipo specificato. ConfigurationBinder.Get<T> può risultare più utile rispetto all'uso di ConfigurationBinder.Bind. Il codice seguente mostra come usare ConfigurationBinder.Get<T> con la classe PositionOptions:

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

Nel codice precedente, per impostazione predefinita, le modifiche apportate al file di configurazione JSON dopo l'avvio dell'app vengono lette.

Un approccio alternativo quando si usa il modello opzioni consiste nell'associare la sezione Position e aggiungerla al contenitore del servizio di inserimento di dipendenze. Nel codice seguente PositionOptions viene aggiunta al contenitore del servizio con Configure e associata alla configurazione:

using ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

Quando si usa il codice precedente, il codice seguente legge le opzioni di posizione:

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

Nel codice precedente le modifiche al file di configurazione JSON dopo l'avvio dell'app non vengono lette. Per leggere le modifiche dopo l'avvio dell'app, usare IOptionsSnapshot.

Quando si usa la configurazione predefinita, i file appsettings.json e appsettings.{Environment}.json sono abilitati con reloadOnChange: true. Le modifiche apportate al appsettings.json file e appsettings.{Environment}.json dopo l'avvio dell'app vengono lette dal provider di configurazione JSON.

Per informazioni sull'aggiunta di file di configurazione JSON aggiuntivi, vedere Provider di configurazione JSON in questo documento.

Combinazione della raccolta di servizi

Considerare il codice seguente che registra i servizi e configura le opzioni:

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();

I gruppi correlati di registrazioni possono essere spostati in un metodo di estensione per registrare i servizi. Ad esempio, i servizi di configurazione vengono aggiunti alla classe seguente:

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

        public static IServiceCollection AddMyDependencyGroup(
             this IServiceCollection services)
        {
            services.AddScoped<IMyDependency, MyDependency>();
            services.AddScoped<IMyDependency2, MyDependency2>();

            return services;
        }
    }
}

I servizi rimanenti vengono registrati in una classe simile. Il codice seguente usa i nuovi metodi di estensione per registrare i servizi:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

Nota: ogni metodo di estensione services.Add{GROUP_NAME} aggiunge e configura potenzialmente i servizi. Ad esempio, AddControllersWithViews aggiunge i controller MVC dei servizi con visualizzazioni richiesti e AddRazorPages aggiunge le pagina Razor dei servizi richieste.

Sicurezza e segreti dell'utente

Linee guida per i dati di configurazione:

  • Non archiviare mai la password o altri dati sensibili nel codice del provider di configurazione o in file di configurazione di testo normale. Per l'archiviazione di segreti per lo sviluppo, è possibile usare lo strumento Secret Manager.
  • Non usare i segreti di produzione in ambienti di sviluppo o di test.
  • Specificare i segreti all'esterno del progetto in modo che non possano essere inavvertitamente inviati a un repository del codice sorgente.
  • Le app di produzione devono usare il flusso di autenticazione più sicuro disponibile. Per altre informazioni, vedere Proteggere i flussi di autenticazione.

Per impostazione predefinita, l'origine di configurazione dei segreti utente viene registrata dopo le origini di configurazione JSON. Pertanto, le chiavi dei segreti dell'utente hanno la precedenza sulle chiavi in appsettings.json e appsettings.{Environment}.json.

Per altre informazioni sull'archiviazione di password o altri dati sensibili:

Azure Key Vault archivia in modo sicuro i segreti delle app ASP.NET Core. Per altre informazioni, vedere Provider di configurazione di Azure Key Vault in ASP.NET Core.

Variabili di ambiente senza prefisso

Le variabili di ambiente senza prefisso sono variabili di ambiente diverse da quelle precedute da ASPNETCORE_ o DOTNET_. Ad esempio, i modelli di applicazione Web ASP.NET Core impostano "ASPNETCORE_ENVIRONMENT": "Development" in launchSettings.json. Per altre informazioni sulle variabili di ambiente ASPNETCORE_ e DOTNET_, vedere:

Quando si usa la configurazione predefinita, EnvironmentVariablesConfigurationProvider carica la configurazione dalle coppie chiave-valore delle variabili di ambiente dopo la lettura di appsettings.json, appsettings.{Environment}.json e dei segreti dell'utente. Therefore, i valori di chiave letti dall'ambiente sostituiscono i valori letti da appsettings.json, appsettings.{Environment}.json e dai segreti dell'utente.

Il separatore : non funziona con le chiavi gerarchiche delle variabili di ambiente in tutte le piattaforme. Ad esempio, il : separatore non è supportato da Bash. Il doppio carattere di sottolineatura, __, è:

  • Supportato da tutte le piattaforme.
  • Sostituito automaticamente da due punti, :.

I comandi set seguenti:

  • Impostano le chiavi e i valori di ambiente dell'esempio precedente in Windows.
  • Testano le impostazioni quando viene usato il download di esempio. Il comando dotnet run deve essere eseguito nella directory del progetto.
set MyKey="My key from Environment"
set Position__Title=Environment_Editor
set Position__Name=Environment_Rick
dotnet run

Le impostazioni dell'ambiente precedenti:

  • Sono impostate solo nei processi avviati dalla finestra di comando in cui sono stati impostate.
  • Non verranno lette dai browser avviati con Visual Studio.

I comandi setx seguenti possono essere usati per impostare le chiavi e i valori di ambiente in Windows. A differenza di set, le impostazioni setx vengono mantenute. /M imposta la variabile nell'ambiente di sistema. Se non viene usata l'opzione /M, viene impostata una variabile di ambiente dell'utente.

setx MyKey "My key from setx Environment" /M
setx Position__Title Environment_Editor /M
setx Position__Name Environment_Rick /M

Per verificare che i comandi precedenti sostituiscano appsettings.json e appsettings.{Environment}.json:

  • Con Visual Studio: uscire e riavviare Visual Studio.
  • Con l'interfaccia della riga di comando: avviare una nuova finestra di comando e immettere dotnet run.

Chiamare AddEnvironmentVariables con una stringa per specificare un prefisso per le variabili di ambiente:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

Nel codice precedente:

Il prefisso viene rimosso quando vengono lette le coppie chiave-valore della configurazione.

I comandi seguenti testano il prefisso personalizzato:

set MyCustomPrefix_MyKey="My key with MyCustomPrefix_ Environment"
set MyCustomPrefix_Position__Title=Editor_with_customPrefix
set MyCustomPrefix_Position__Name=Environment_Rick_cp
dotnet run

La configurazione predefinita carica le variabili di ambiente e gli argomenti della riga di comando con prefisso DOTNET_ e ASPNETCORE_. I prefissi DOTNET_ e ASPNETCORE_ vengono usati da ASP.NET Core per la configurazione dell'host e dell'app, ma non per la configurazione dell'utente. Per altre informazioni sulla configurazione dell'host e dell'app, vedere Host generico .NET.

In Servizio app di Azure selezionare Nuova impostazione applicazione nella pagina Impostazioni > Configurazione. Le impostazioni applicazione del Servizio app di Azure sono:

  • Crittografato in e rest trasmesso tramite un canale crittografato.
  • Esposte come variabili di ambiente.

Per altre informazioni, vedere App di Azure: Eseguire l'override della configurazione delle app usando il portale di Azure.

Per informazioni sulle stringhe di connessione del database di Azure, vedere Prefissi della stringa di connessione.

Denominazione delle variabili di ambiente

I nomi delle variabili di ambiente riflettono la struttura di un file appsettings.json. Ogni elemento nella gerarchia è separato da un doppio carattere di sottolineatura (preferibile) o due punti. Quando la struttura dell'elemento include una matrice, l'indice della matrice deve essere considerato come un nome di elemento aggiuntivo in questo percorso. Si consideri il file appsettings.json seguente e i relativi valori equivalenti rappresentati come variabili di ambiente.

appsettings.json

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

variabili di ambiente

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

Variabili di ambiente impostate nel file launchSettings.json generato

Variabili di ambiente impostate in launchSettings.json sostituiscono quelle impostate nell'ambiente di sistema. Ad esempio, i modelli Web ASP.NET Core generano un file launchSettings.json che imposta la configurazione dell'endpoint su:

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

La configurazione di applicationUrl imposta la variabile di ambiente ASPNETCORE_URLS e sostituisce i valori impostati nell'ambiente.

Carattere di escape per le variabili di ambiente in Linux

In Linux il valore delle variabili di ambiente degli URL deve essere preceduto da un carattere di escape in modo che systemd possa analizzarle. Usare lo strumento linux systemd-escape che restituisce http:--localhost:5001

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

Visualizzare le variabili di ambiente

Il codice seguente visualizza le variabili di ambiente e i valori all'avvio dell'applicazione, utile durante il debug delle impostazioni di ambiente:

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

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

Riga di comando

Quando si usa la configurazione predefinita, CommandLineConfigurationProvider carica la configurazione dalle coppie chiave-valore degli argomenti della riga di comando dopo le origini di configurazione seguenti:

  • File appsettings.json e appsettings.{Environment}.json.
  • Segreti dell'app nell'ambiente di sviluppo.
  • variabili di ambiente.

Per impostazione predefinita, i valori di configurazione impostati nella riga di comando sostituiscono i valori di configurazione impostati con tutti gli altri provider di configurazione.

Argomenti della riga di comando

Il comando seguente imposta chiavi e valori usando =:

dotnet run MyKey="Using =" Position:Title=Cmd Position:Name=Cmd_Rick

Il comando seguente imposta chiavi e valori usando /:

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

Il comando seguente imposta chiavi e valori usando --:

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

Il valore di chiave:

  • Deve seguire = o la chiave deve avere un prefisso -- o / quando il valore segue uno spazio.
  • Non è richiesto se viene usato =. Ad esempio: MySetting=.

Nello stesso comando, non mischiare coppie chiave-valore di argomenti della riga di comando che usano = con coppie chiave-valore che usano uno spazio.

Mapping di sostituzione

I mapping di sostituzione consentono di usare la logica di sostituzione del nome della chiave. Specificare un dizionario delle sostituzioni al metodo AddCommandLine.

Quando viene utilizzato il dizionario dei mapping di sostituzione, nel dizionario viene controllata la presenza di una chiave corrispondente alla chiave fornita da un argomento della riga di comando. Se la chiave della riga di comando viene trovata nel dizionario, il valore del dizionario viene passato nuovamente per impostare la coppia chiave-valore nella configurazione dell'app. Un mapping di sostituzione è necessario per le chiavi della riga di comando con un trattino singolo (-) come prefisso.

Regole principali del dizionario dei mapping di sostituzione:

  • Le sostituzioni devono iniziare con - o --.
  • Il dizionario dei mapping di sostituzione non deve contenere chiavi duplicate.

Per usare un dizionario dei mapping di sostituzione, passarlo nella chiamata a AddCommandLine:


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();

Per testare la sostituzione delle chiavi è possibile eseguire il comando seguente:

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

Il codice seguente mostra i valori di chiave per le chiavi sostituite:

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"]}'");
    }
}

Per le app che usano i mapping di sostituzione, la chiamata a CreateDefaultBuilder non deve passare argomenti. La chiamata AddCommandLine del metodo CreateDefaultBuilder non include sostituzioni mappate e non è possibile passare il dizionario dei mapping di sostituzione a CreateDefaultBuilder. La soluzione non consiste nel passare gli argomenti a CreateDefaultBuilder ma nel consentire al metodo AddCommandLine del metodo ConfigurationBuilder di elaborare entrambi gli argomenti e il dizionario dei mapping di sostituzione.

Impostare gli argomenti dell'ambiente e della riga di comando con Visual Studio

Gli argomenti dell'ambiente e della riga di comando possono essere impostati in Visual Studio dalla finestra dei profili di avvio:

  • In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e selezionare Proprietà.
  • Selezionare la scheda Debug > Generale e selezionare Aprire interfaccia utente profili di avvio debug.

Dati di configurazione gerarchici

L'API di configurazione legge i dati di configurazione gerarchici rendendoli flat grazie all'uso di un delimitatore nelle chiavi di configurazione.

Il download di esempio contiene il file appsettings.json seguente:

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

Il codice seguente del download di esempio visualizza diverse impostazioni delle configurazioni:

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

Il modo preferito per leggere i dati di configurazione gerarchici prevede l'uso del modello di opzioni. Per altre informazioni, vedere Associare dati di configurazione gerarchici in questo documento.

I metodi GetSection e GetChildren sono disponibili per isolare le sezioni e gli elementi figlio di una sezione nei dati di configurazione. Questi metodi sono descritti più avanti in GetSection, GetChildren ed Exists.

Chiavi e valori di configurazione

Avviso

Questo articolo illustra l'uso di stringa di connessione. Con un database locale l'utente non deve essere autenticato, ma nell'ambiente di produzione stringa di connessione talvolta include una password per l'autenticazione. Una credenziale della password del proprietario della risorsa (ROPC) è un rischio per la sicurezza che deve essere evitato nei database di produzione. Le app di produzione devono usare il flusso di autenticazione più sicuro disponibile. Per altre informazioni sull'autenticazione per le app distribuite in ambienti di test o di produzione, vedere Proteggere i flussi di autenticazione.

Chiavi di configurazione:

  • non viene fatta distinzione tra maiuscole e minuscole. Ad esempio, ConnectionString e connectionstring vengono considerate chiavi equivalenti.
  • Se una chiave e un valore vengono impostati in più di un provider di configurazione, viene usato il valore dell'ultimo provider aggiunto. Per altre informazioni, vedere Configurazione predefinita.
  • Chiavi gerarchica
    • Nell'ambito dell'API di configurazione, il separatore due punti (:) funziona in tutte le piattaforme.
    • Nelle variabili di ambiente, un separatore due punti potrebbe non funzionare in tutte le piattaforme. Il doppio carattere di sottolineatura, __, è supportato da tutte le piattaforme e viene convertito automaticamente nei due punti :.
    • In Azure Key Vault le chiavi gerarchiche usano -- come separatore. Il provider di configurazione di Azure Key Vault sostituisce automaticamente -- con : quando i segreti vengono caricati nella configurazione dell'app.
  • Il ConfigurationBinder supporta l'associazione di matrici agli oggetti usando gli indici delle matrici nelle chiavi di configurazione. L'associazione di matrici è descritta nella sezione Associare una matrice a una classe.

Valori di configurazione:

  • sono stringhe.
  • I valori null non possono essere archiviati nella configurazione o associati a oggetti.

Provider di configurazione

La tabella seguente mostra i provider di configurazione disponibili per le app ASP.NET Core.

Provider Fornisce la configurazione da
Azure Key Vault configuration provider (Provider di configurazione di Azure Key Vault) Azure Key Vault
Provider di configurazione app di Azure Configurazione app di Azure
Provider di configurazione della riga di comando Parametri della riga di comando
Provider di configurazione personalizzato Origine personalizzata
Provider di configurazione delle variabili di ambiente Variabili di ambiente
Provider di configurazione file File INI, JSON e XML
Provider di configurazione chiave-per-file File della directory
Provider di configurazione della memoria Raccolte in memoria
Segreti utente File nella directory dei profili utente

Le origini di configurazione vengono lette nell'ordine in cui vengono specificati i rispetti provider di configurazione. Ordinare i provider di configurazione nel codice in base alle priorità per le origini di configurazione sottostanti richieste dall'app.

Una sequenza tipica di provider di configurazione è:

  1. appsettings.json
  2. appsettings.{Environment}.json
  3. Segreti utente
  4. Variabili di ambiente che usano il provider di configurazione delle variabili di ambiente.
  5. Argomenti della riga di comando che usano il provider di configurazione della riga di comando.

È pratica comune aggiungere il provider di configurazione della riga di comando per ultimo in una serie di provider per consentire agli argomenti della riga di comando di sostituire la configurazione impostata da altri provider.

La sequenza di provider precedente è usata nella configurazione predefinita.

Prefissi della stringa di connessione

Avviso

Questo articolo illustra l'uso di stringa di connessione. Con un database locale l'utente non deve essere autenticato, ma nell'ambiente di produzione stringa di connessione talvolta include una password per l'autenticazione. Una credenziale della password del proprietario della risorsa (ROPC) è un rischio per la sicurezza che deve essere evitato nei database di produzione. Le app di produzione devono usare il flusso di autenticazione più sicuro disponibile. Per altre informazioni sull'autenticazione per le app distribuite in ambienti di test o di produzione, vedere Proteggere i flussi di autenticazione.

L'API di configurazione ha regole di elaborazione speciali per quattro variabili di ambiente della stringa di connessione. Queste stringhe di connessione sono coinvolte nella configurazione delle stringhe di connessione di Azure per l'ambiente dell'app. Le variabili di ambiente con i prefissi indicati nella tabella vengono caricate nell'app con la configurazione predefinita o quando non viene specificato alcun prefisso per AddEnvironmentVariables.

Prefisso della stringa di connessione Provider
CUSTOMCONNSTR_ Provider personalizzato
MYSQLCONNSTR_ MySQL
SQLAZURECONNSTR_ Database SQL di Azure
SQLCONNSTR_ SQL Server

Quando una variabile di ambiente viene individuata e caricata nella configurazione con uno qualsiasi dei quattro prefissi indicati nella tabella:

  • La chiave di configurazione viene creata rimuovendo il prefisso della variabile di ambiente e aggiungendo una sezione per la chiave di configurazione (ConnectionStrings).
  • Viene creata una nuova coppia chiave-valore della configurazione che rappresenta il provider di connessione al database (ad eccezione di CUSTOMCONNSTR_, che non ha un provider dichiarato).
Chiave della variabile di ambiente Chiave di configurazione convertita Voce di configurazione del provider
CUSTOMCONNSTR_{KEY} ConnectionStrings:{KEY} Voce di configurazione non creata.
MYSQLCONNSTR_{KEY} ConnectionStrings:{KEY} Chiave: ConnectionStrings:{KEY}_ProviderName:
Valore: MySql.Data.MySqlClient
SQLAZURECONNSTR_{KEY} ConnectionStrings:{KEY} Chiave: ConnectionStrings:{KEY}_ProviderName:
Valore: System.Data.SqlClient
SQLCONNSTR_{KEY} ConnectionStrings:{KEY} Chiave: ConnectionStrings:{KEY}_ProviderName:
Valore: System.Data.SqlClient

Provider di configurazione file

FileConfigurationProvider è la classe base per il caricamento della configurazione dal file system. I provider di configurazione seguenti derivano da FileConfigurationProvider:

Provider di configurazione INI

IniConfigurationProvider carica la configurazione da coppie chiave-valore di file INI in fase di esecuzione.

Il codice seguente aggiunge diversi provider di configurazione:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddIniFile("MyIniConfig.ini", optional: true, reloadOnChange: true)
    .AddIniFile($"MyIniConfig.{builder.Environment.EnvironmentName}.ini",
                optional: true, reloadOnChange: true);

builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

Nel codice precedente le impostazioni nei file MyIniConfig.ini e MyIniConfig.{Environment}.ini sono sostituite dalle impostazioni in:

Il download di esempio contiene il file MyIniConfig.ini seguente:

MyKey="MyIniConfig.ini Value"

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

[Logging:LogLevel]
Default=Information
Microsoft=Warning

Il codice seguente del download di esempio visualizza diverse impostazioni delle configurazioni precedenti:

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

Provider di configurazione JSON

Carica JsonConfigurationProvider la configurazione dalle coppie chiave-valore del file JSON.

Gli overload possono specificare:

  • Se il file è facoltativo.
  • Se la configurazione viene ricaricata se viene modificato il file.

Osservare il codice seguente:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddJsonFile("MyConfig.json",
        optional: true,
        reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

Il codice precedente:

In genere non si vuole che un file JSON personalizzato sostituisci i valori impostati nel provider di configurazione delle variabili di ambiente e nel provider di configurazione della riga di comando.

Provider di configurazione XML

Il XmlConfigurationProvider carica la configurazione da coppie chiave-valore di file XML in fase di esecuzione.

Il codice seguente aggiunge diversi provider di configurazione:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddXmlFile("MyXMLFile.xml", optional: true, reloadOnChange: true)
    .AddXmlFile($"MyXMLFile.{builder.Environment.EnvironmentName}.xml",
                optional: true, reloadOnChange: true);

builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

Nel codice precedente le impostazioni nei file MyXMLFile.xml e MyXMLFile.{Environment}.xml sono sostituite dalle impostazioni in:

Il download di esempio contiene il file MyXMLFile.xml seguente:

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

Il codice seguente del download di esempio visualizza diverse impostazioni delle configurazioni precedenti:

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

La ripetizione di elementi che usano lo stesso nome di elemento funziona se si usa l'attributo name per distinguere gli elementi:

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

Il codice seguente legge il file di configurazione precedente e visualizza le chiavi e i valori:

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

È possibile usare attributi per fornire valori:

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

Il file di configurazione precedente carica le chiavi seguenti con value:

  • key:attribute
  • section:key:attribute

Provider di configurazione chiave-per-file

Il KeyPerFileConfigurationProvider usa i file di una directory come coppie chiave-valore della configurazione. La chiave è il nome del file. Il valore contiene il contenuto del file. Il provider di configurazione chiave-per-file viene usato negli scenari di hosting di Docker.

Per attivare la configurazione chiave-per-file, chiamare il metodo di estensione AddKeyPerFile su un'istanza di ConfigurationBuilder. Il directoryPath per i file deve essere un percorso assoluto.

Gli overload consentono di specificare:

  • Un delegato Action<KeyPerFileConfigurationSource> che configura l'origine.
  • Se la directory è facoltativa e il percorso della directory.

Il doppio carattere di sottolineatura (__) viene usato come delimitatore per le chiavi di configurazione nei nomi dei file. Ad esempio, il nome di file Logging__LogLevel__System produce la chiave di configurazione Logging:LogLevel:System.

Chiamare ConfigureAppConfiguration quando si crea l'host per specificare la configurazione dell'app:

.ConfigureAppConfiguration((hostingContext, config) =>
{
    var path = Path.Combine(
        Directory.GetCurrentDirectory(), "path/to/files");
    config.AddKeyPerFile(directoryPath: path, optional: true);
})

Provider di configurazione della memoria

Il MemoryConfigurationProvider usa una raccolta in memoria come coppie chiave-valore della configurazione.

Il codice seguente aggiunge una raccolta di memoria al sistema di configurazione:

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.Configuration.AddInMemoryCollection(Dict);
builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

Il codice seguente del download di esempio visualizza le impostazioni delle configurazioni precedenti:

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

Nel codice precedente config.AddInMemoryCollection(Dict) viene aggiunto dopo i provider di configurazione predefiniti. Per un esempio di ordinamento dei provider di configurazione, vedere Provider di configurazione JSON.

Vedere Associare una matrice per un altro esempio che usa MemoryConfigurationProvider.

Configurazione di endpoint Kestrel

La configurazione di endpoint specifica di Kestrel sostituisce tutte le configurazioni di endpoint tra server. Le configurazioni di endpoint tra server includono:

Si consideri il file appsettings.json seguente usato in un'app Web ASP.NET Core:

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

Quando il markup evidenziato precedente viene usato in un'app Web ASP.NET Core e l'app viene avviata dalla riga di comando con la configurazione dell'endpoint tra server seguente:

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

Kestrel si associa all'endpoint configurato specificatamente per Kestrel nel file appsettings.json (https://localhost:9999) e non in https://localhost:7777.

Si consideri l'endpoint specifico di Kestrel configurato come variabile di ambiente:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

nella variabile di ambiente precedente Https è il nome dell'endpoint specifico di Kestrel. Il file appsettings.json precedente definisce anche un endpoint specifico di Kestrel denominato Https. Per impostazione predefinita, le variabili di ambiente che usano il provider di configurazione delle variabili di ambiente vengono lette dopo appsettings.{Environment}.json, di conseguenza la variabile di ambiente precedente viene usata per l'endpoint Https.

GetValue

ConfigurationBinder.GetValue estrae un valore dalla configurazione con una chiave specificata e lo converte nel tipo specificato:

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

Nel codice precedente, se NumberKey non viene trovato nella configurazione, viene usato il valore predefinito di 99.

GetSection, GetChildren ed Exists

Per gli esempi che seguono, prendere in considerazione il file MySubsection.json seguente:

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

Il codice seguente aggiunge MySubsection.json ai provider di configurazione:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddJsonFile("MySubsection.json",
                 optional: true,
                 reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

GetSection

IConfiguration.GetSection restituisce una sottosezione della configurazione con la chiave di sottosezione specificata.

Il codice seguente restituisce i valori per section1:

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"]}'");
    }
}

Il codice seguente restituisce i valori per section2:subsection0:

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 non restituisce mai null. Se non viene trovata una sezione corrispondente, viene restituita una IConfigurationSection vuota.

Quando GetSection restituisce una sezione corrispondente, Value non viene compilata. Quando la sezione esiste, vengono restituiti Key e Path.

GetChildren ed Exists

Il codice seguente chiama IConfiguration.GetChildren e restituisce i valori per section2:subsection0:

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

Il codice precedente chiama ConfigurationExtensions.Exists per verificare che la sezione esista:

Associare una matrice

Il ConfigurationBinder.Bind supporta l'associazione di matrici agli oggetti usando gli indici delle matrici nelle chiavi di configurazione. Qualsiasi formato di matrice che espone un segmento chiave numerico supporta l'associazione di matrici a una matrice di classi POCO.

Si consideri MyArray.json del download di esempio:

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

Il codice seguente aggiunge MyArray.json ai provider di configurazione:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddJsonFile("MyArray.json",
                 optional: true,
                 reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

Il codice seguente legge la configurazione e visualizza i valori:

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>();
        if (_array == null)
        {
            throw new ArgumentNullException(nameof(_array));
        }
        string s = String.Empty;

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

        return Content(s);
    }
}
public class ArrayExample
{
    public string[]? Entries { get; set; } 
}

Il codice precedente restituisce l'output seguente:

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

Nell'output precedente Index 3 ha il valore value40, corrispondente a "4": "value40", in MyArray.json. Gli indici di matrice associati sono continui e non associati all'indice delle chiavi di configurazione. Il binder di configurazione non supporta l'associazione di valori Null o la creazione di voci Null negli oggetti associati.

Provider di configurazione personalizzato

L'app di esempio dimostra come creare un provider di configurazione di base che legge le coppie chiave-valore di configurazione da un database usando Entity Framework (EF).

Il provider ha le caratteristiche seguenti:

  • Il database in memoria di Entity Framework viene usato a scopo dimostrativo. Per usare un database che richiede una stringa di connessione, implementare un ConfigurationBuilder secondario per fornire la stringa di connessione da un altro provider di configurazione.
  • Il provider legge una tabella di database in una configurazione all'avvio. Il provider non esegue una query sul database per ogni chiave.
  • Il ricaricamento in caso di modifica non è implementato, quindi l'aggiornamento del database dopo l'avvio dell'app non ha alcun effetto sulla configurazione dell'app.

Definire un'entità EFConfigurationValue per l'archiviazione dei valori di configurazione nel database.

Models/EFConfigurationValue.cs:

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

Aggiungere EFConfigurationContext per archiviare i valori configurati e accedervi.

EFConfigurationProvider/EFConfigurationContext.cs:

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

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

Creare una classe che implementi IConfigurationSource.

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

Creare il provider di configurazione personalizzato ereditando da ConfigurationProvider. Il provider di configurazione inizializza il database quando è vuoto. Poiché nelle chiavi di configurazione non viene fatta distinzione tra maiuscole e minuscole, il dizionario usato per inizializzare il database viene creato con l'operatore di confronto senza distinzione tra maiuscole e minuscole (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-2005
        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;
    }
}

Un metodo di estensione AddEFConfiguration consente di aggiungere l'origine di configurazione a un ConfigurationBuilder.

Extensions/EntityFrameworkExtensions.cs:

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

Il codice seguente mostra come usare EFConfigurationProvider personalizzato in Program.cs:

//using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

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

var app = builder.Build();

app.Run();

Configurazione dell'accesso con inserimento delle dipendenze

La configurazione può essere inserita nei servizi usando l'inserimento delle dipendenze attraverso la risoluzione del servizio IConfiguration:

public class Service
{
    private readonly IConfiguration _config;

    public Service(IConfiguration config) =>
        _config = config;

    public void DoSomething()
    {
        var configSettingValue = _config["ConfigSetting"];

        // ...
    }
}

Per informazioni su come accedere ai valori usando IConfiguration, vedere GetValue e GetSection, GetChildren ed Exists in questo articolo.

Accedere alla configurazione nelle pagine Razor

Il codice seguente visualizza i dati di configurazione in una pagina Razor:

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

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

Nel codice seguente MyOptions viene aggiunta al contenitore del servizio con Configure e associata alla configurazione:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

Il markup seguente usa la direttiva @injectRazor per risolvere e visualizzare i valori delle opzioni:

@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>

Accedere alla configurazione in un file di visualizzazione MVC

Il codice seguente visualizza i dati di configurazione in una visualizzazione MVC:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

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

Accedere alla configurazione in Program.cs

Il codice seguente accede alla configurazione nel file Program.cs.

var builder = WebApplication.CreateBuilder(args);

var key1 = builder.Configuration.GetValue<string>("KeyOne");

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

var key2 = app.Configuration.GetValue<int>("KeyTwo");
var key3 = app.Configuration.GetValue<bool>("KeyThree");

app.Logger.LogInformation("KeyOne: {KeyOne}", key1);
app.Logger.LogInformation("KeyTwo: {KeyTwo}", key2);
app.Logger.LogInformation("KeyThree: {KeyThree}", key3);

app.Run();

In appsettings.json per l'esempio precedente:

{
  ...
  "KeyOne": "Key One Value",
  "KeyTwo": 1999,
  "KeyThree": true
}

Configurare opzioni con un delegato

Le opzioni configurate in un delegato sostituiscono i valori impostati nei provider di configurazione.

Nel codice seguente viene aggiunto un servizio IConfigureOptions<TOptions> al contenitore di servizi. Viene usato un delegato per configurare i valori per MyOptions:

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();

Il codice seguente visualizza i valori delle opzioni:

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

Nell'esempio precedente i valori di Option1 e Option2 sono specificati in appsettings.json e quindi sostituiti dal delegato configurato.

Host e configurazione delle app

Prima che l'app venga configurata e avviata, viene configurato e avviato un host. L'host è responsabile della gestione dell'avvio e della durata delle app. Sia l'app che l'host vengono configurati tramite i provider di configurazione descritti in questo argomento. Anche le coppie chiave-valore di configurazione dell'host sono incluse nella configurazione dell'app. Per altre informazioni su come vengono usati i provider di configurazione per la creazione dell'host e sugli effetti delle origini di configurazione sulla configurazione dell'host, vedere Panoramica delle nozioni di base su ASP.NET Core.

Configurazione dell'host predefinita

Per informazioni dettagliate sulla configurazione predefinita quando viene usato l'host Web, vedere la versione di questo argomento per ASP.NET Core 2.2.

  • La configurazione dell'host viene fornita da:
  • Viene stabilita la configurazione predefinita dell'host Web (ConfigureWebHostDefaults):
    • Kestrel viene usato come server Web e configurato con i provider di configurazione dell'app.
    • Aggiungere il middleware di filtro host.
    • Aggiungere il middleware delle intestazioni inoltrate se la variabile di ambiente ASPNETCORE_FORWARDEDHEADERS_ENABLED è impostata su true.
    • Abilitare l'integrazione di IIS.

Altra configurazione

Questo argomento riguarda solo la configurazione dell'app. Altri aspetti dell'esecuzione e dell'hosting delle app ASP.NET Core vengono configurati usando i file di configurazione non descritti in questo argomento:

Variabili di ambiente impostate in launchSettings.json sostituiscono quelle impostate nell'ambiente di sistema.

Per altre informazioni sulla migrazione della configurazione dell'app da versioni precedenti di ASP.NET, vedere Eseguire l'aggiornamento da ASP.NET a ASP.NET Core.

Aggiungere la configurazione da un assembly esterno

Un'implementazione IHostingStartup consente l'aggiunta di miglioramenti a un'app all'avvio, da un assembly esterno alla classe Startup dell'app. Per altre informazioni, vedere Usare assembly di avvio dell'hosting in ASP.NET Core.

Risorse aggiuntive

Configurazione di endpoint Kestrel

La configurazione di endpoint specifica di Kestrel sostituisce tutte le configurazioni di endpoint tra server. Le configurazioni di endpoint tra server includono:

Si consideri il file appsettings.json seguente usato in un'app Web ASP.NET Core:

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

Quando il markup evidenziato precedente viene usato in un'app Web ASP.NET Core e l'app viene avviata dalla riga di comando con la configurazione dell'endpoint tra server seguente:

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

Kestrel si associa all'endpoint configurato specificatamente per Kestrel nel file appsettings.json (https://localhost:9999) e non in https://localhost:7777.

Si consideri l'endpoint specifico di Kestrel configurato come variabile di ambiente:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

nella variabile di ambiente precedente Https è il nome dell'endpoint specifico di Kestrel. Il file appsettings.json precedente definisce anche un endpoint specifico di Kestrel denominato Https. Per impostazione predefinita, le variabili di ambiente che usano il provider di configurazione delle variabili di ambiente vengono lette dopo appsettings.{Environment}.json, di conseguenza la variabile di ambiente precedente viene usata per l'endpoint Https.

GetValue

ConfigurationBinder.GetValue estrae un singolo valore dalla configurazione con una chiave specificata e lo converte nel tipo specificato. Questo metodo è un metodo di estensione per IConfiguration:

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

Nel codice precedente, se NumberKey non viene trovato nella configurazione, viene usato il valore predefinito di 99.

GetSection, GetChildren ed Exists

Per gli esempi che seguono, prendere in considerazione il file MySubsection.json seguente:

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

Il codice seguente aggiunge MySubsection.json ai provider di configurazione:

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 restituisce una sottosezione della configurazione con la chiave di sottosezione specificata.

Il codice seguente restituisce i valori per section1:

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"]}'");
    }
}

Il codice seguente restituisce i valori per section2:subsection0:

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 non restituisce mai null. Se non viene trovata una sezione corrispondente, viene restituita una IConfigurationSection vuota.

Quando GetSection restituisce una sezione corrispondente, Value non viene compilata. Quando la sezione esiste, vengono restituiti Key e Path.

GetChildren ed Exists

Il codice seguente chiama IConfiguration.GetChildren e restituisce i valori per section2:subsection0:

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

Il codice precedente chiama ConfigurationExtensions.Exists per verificare che la sezione esista:

Associare una matrice

Il ConfigurationBinder.Bind supporta l'associazione di matrici agli oggetti usando gli indici delle matrici nelle chiavi di configurazione. Qualsiasi formato di matrice che espone un segmento chiave numerico supporta l'associazione di matrici a una matrice di classi POCO.

Si consideri MyArray.json del download di esempio:

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

Il codice seguente aggiunge MyArray.json ai provider di configurazione:

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

Il codice seguente legge la configurazione e visualizza i valori:

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

Il codice precedente restituisce l'output seguente:

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

Nell'output precedente Index 3 ha il valore value40, corrispondente a "4": "value40", in MyArray.json. Gli indici di matrice associati sono continui e non associati all'indice delle chiavi di configurazione. Il binder di configurazione non supporta l'associazione di valori Null o la creazione di voci Null negli oggetti associati

Il codice seguente carica la configurazione array:entries con il metodo di estensione AddInMemoryCollection:

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

Il codice seguente legge la configurazione in arrayDict Dictionary e visualizza i valori:

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

Il codice precedente restituisce l'output seguente:

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

L'indice #3 nell'oggetto associato contiene i dati di configurazione per la chiave di configurazione array:4 e il relativo valore di value4. Quando i dati di configurazione contenenti una matrice vengono associati, gli indici di matrice nelle chiavi di configurazione vengono usati per scorrere i dati di configurazione quando si crea l'oggetto. Un valore null non può essere mantenuto nei dati di configurazione e una voce con valore null non viene creata in un oggetto associato quando una matrice nelle chiavi di configurazione ignora uno o più indici.

L'elemento di configurazione mancante per l'indice #3 può essere fornito prima dell'associazione all'istanza ArrayExample da qualsiasi provider di configurazione che legge la coppia chiave-valore dell'indice #3. Si consideri il file Value3.json seguente del download di esempio:

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

Il codice seguente include la configurazione per Value3.json e :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>();
            });
    }
}

Il codice seguente legge la configurazione precedente e visualizza i valori:

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

Il codice precedente restituisce l'output seguente:

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

I provider di configurazione personalizzati non devono implementare l'associazione di matrici.

Provider di configurazione personalizzato

Avviso

Questo articolo illustra l'uso di stringa di connessione. Con un database locale l'utente non deve essere autenticato, ma nell'ambiente di produzione stringa di connessione talvolta include una password per l'autenticazione. Una credenziale della password del proprietario della risorsa (ROPC) è un rischio per la sicurezza che deve essere evitato nei database di produzione. Le app di produzione devono usare il flusso di autenticazione più sicuro disponibile. Per altre informazioni sull'autenticazione per le app distribuite in ambienti di test o di produzione, vedere Proteggere i flussi di autenticazione.

L'app di esempio dimostra come creare un provider di configurazione di base che legge le coppie chiave-valore di configurazione da un database usando Entity Framework (EF).

Il provider ha le caratteristiche seguenti:

  • Il database in memoria di Entity Framework viene usato a scopo dimostrativo. Per usare un database che richiede una stringa di connessione, implementare un ConfigurationBuilder secondario per fornire la stringa di connessione da un altro provider di configurazione.
  • Il provider legge una tabella di database in una configurazione all'avvio. Il provider non esegue una query sul database per ogni chiave.
  • Il ricaricamento in caso di modifica non è implementato, quindi l'aggiornamento del database dopo l'avvio dell'app non ha alcun effetto sulla configurazione dell'app.

Definire un'entità EFConfigurationValue per l'archiviazione dei valori di configurazione nel database.

Models/EFConfigurationValue.cs:

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

Aggiungere EFConfigurationContext per archiviare i valori configurati e accedervi.

EFConfigurationProvider/EFConfigurationContext.cs:

// using Microsoft.EntityFrameworkCore;

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

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

Creare una classe che implementi IConfigurationSource.

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

Creare il provider di configurazione personalizzato ereditando da ConfigurationProvider. Il provider di configurazione inizializza il database quando è vuoto. Poiché nelle chiavi di configurazione non viene fatta distinzione tra maiuscole e minuscole, il dizionario usato per inizializzare il database viene creato con l'operatore di confronto senza distinzione tra maiuscole e minuscole (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-2005
        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;
    }
}

Un metodo di estensione AddEFConfiguration consente di aggiungere l'origine di configurazione a un ConfigurationBuilder.

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

Il codice seguente mostra come usare EFConfigurationProvider personalizzato in Program.cs:

// using Microsoft.EntityFrameworkCore;

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

Accedere alla configurazione in Avvio

Il codice seguente visualizza i dati di configurazione nei metodi Startup:

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

Per un esempio di accesso alla configurazione usando metodi di servizio di avvio, vedere Avvio dell'applicazione: Metodi pratici.

Accedere alla configurazione nelle pagine Razor

Il codice seguente visualizza i dati di configurazione in una pagina Razor:

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

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

Nel codice seguente MyOptions viene aggiunta al contenitore del servizio con Configure e associata alla configurazione:

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

    services.AddRazorPages();
}

Il markup seguente usa la direttiva @injectRazor per risolvere e visualizzare i valori delle opzioni:

@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>

Accedere alla configurazione in un file di visualizzazione MVC

Il codice seguente visualizza i dati di configurazione in una visualizzazione MVC:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

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

Configurare opzioni con un delegato

Le opzioni configurate in un delegato sostituiscono i valori impostati nei provider di configurazione.

La configurazione di opzioni con un delegato è illustrata nell'Esempio 2 nell'app di esempio.

Nel codice seguente viene aggiunto un servizio IConfigureOptions<TOptions> al contenitore di servizi. Viene usato un delegato per configurare i valori per MyOptions:

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

    services.AddRazorPages();
}

Il codice seguente visualizza i valori delle opzioni:

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

Nell'esempio precedente i valori di Option1 e Option2 sono specificati in appsettings.json e quindi sostituiti dal delegato configurato.

Host e configurazione delle app

Prima che l'app venga configurata e avviata, viene configurato e avviato un host. L'host è responsabile della gestione dell'avvio e della durata delle app. Sia l'app che l'host vengono configurati tramite i provider di configurazione descritti in questo argomento. Anche le coppie chiave-valore di configurazione dell'host sono incluse nella configurazione dell'app. Per altre informazioni su come vengono usati i provider di configurazione per la creazione dell'host e sugli effetti delle origini di configurazione sulla configurazione dell'host, vedere Panoramica delle nozioni di base su ASP.NET Core.

Configurazione dell'host predefinita

Per informazioni dettagliate sulla configurazione predefinita quando viene usato l'host Web, vedere la versione di questo argomento per ASP.NET Core 2.2.

  • La configurazione dell'host viene fornita da:
    • Variabili di ambiente con prefisso DOTNET_ (ad esempio, DOTNET_ENVIRONMENT) che usano il provider di configurazione delle variabili di ambiente. Il prefisso (DOTNET_) viene rimosso al caricamento delle coppie chiave-valore della configurazione.
    • Argomenti della riga di comando che usano il provider di configurazione della riga di comando.
  • Viene stabilita la configurazione predefinita dell'host Web (ConfigureWebHostDefaults):
    • Kestrel viene usato come server Web e configurato con i provider di configurazione dell'app.
    • Aggiungere il middleware di filtro host.
    • Aggiungere il middleware delle intestazioni inoltrate se la variabile di ambiente ASPNETCORE_FORWARDEDHEADERS_ENABLED è impostata su true.
    • Abilitare l'integrazione di IIS.

Altra configurazione

Questo argomento riguarda solo la configurazione dell'app. Altri aspetti dell'esecuzione e dell'hosting delle app ASP.NET Core vengono configurati usando i file di configurazione non descritti in questo argomento:

Variabili di ambiente impostate in launchSettings.json sostituiscono quelle impostate nell'ambiente di sistema.

Per altre informazioni sulla migrazione della configurazione dell'app da versioni precedenti di ASP.NET, vedere Eseguire l'aggiornamento da ASP.NET a ASP.NET Core.

Aggiungere la configurazione da un assembly esterno

Un'implementazione IHostingStartup consente l'aggiunta di miglioramenti a un'app all'avvio, da un assembly esterno alla classe Startup dell'app. Per altre informazioni, vedere Usare assembly di avvio dell'hosting in ASP.NET Core.

Risorse aggiuntive