Proveedores de configuración en .NET

La configuración en .NET se realiza con proveedores de configuración. Hay varios tipos de proveedores que dependen de varios orígenes de configuración. En este artículo se detallan los distintos proveedores de configuración y sus orígenes correspondientes.

Proveedor de configuración de archivo

FileConfigurationProvider es la clase base para cargar la configuración del sistema de archivos. Los siguientes proveedores de configuración se derivan de FileConfigurationProvider:

Proveedor de configuración JSON

La clase JsonConfigurationProvider carga la configuración desde un archivo JSON. Instale el paquete NuGet Microsoft.Extensions.Configuration.Json.

Las sobrecargas pueden especificar:

  • Si el archivo es opcional.
  • Si la configuración se recarga si el archivo cambia.

Observe el código siguiente:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

namespace ConsoleJson.Example;

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

        // Application code should start here.

        await host.RunAsync();
    }

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

                IHostEnvironment env = hostingContext.HostingEnvironment;

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

                IConfigurationRoot configurationRoot = configuration.Build();

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

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

El código anterior:

  • Borra todos los proveedores de configuración existentes que se agregaron de forma predeterminada en el método CreateDefaultBuilder(String[]).
  • Configura el proveedor de configuración de JSON para cargar los archivos appsettings.json y appsettings.Environment.json con las siguientes opciones:
    • optional: true: el archivo es opcional.
    • reloadOnChange: true: el archivo se recarga cuando se guardan los cambios.

La configuración de JSON es reemplazada por la configuración del proveedor de configuración de variables de entorno y del proveedor de configuración de línea de comandos.

A continuación se muestra un ejemplo de archivo appsettings.json con varios valores de configuración:

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

Desde la instancia de IConfigurationBuilder, una vez agregados los proveedores de configuración, puede llamar a IConfigurationBuilder.Build() para obtener el objeto IConfigurationRoot. La raíz de configuración representa la raíz de una jerarquía de configuración. Las secciones de la configuración se pueden enlazar a instancias de objetos .NET y, posteriormente, se pueden proporcionar como IOptions<TOptions> mediante la inserción de dependencias.

Nota

Las propiedades Acción de compilación y Copiar en el directorio de salida del archivo JSON deben establecerse en Contenido y Copiar si es posterior (o Copiar siempre) respectivamente.

Observe la clase TransientFaultHandlingOptions definida como se indica a continuación:

namespace ConsoleJson.Example;

public class TransientFaultHandlingOptions
{
    public bool Enabled { get; set; }
    public TimeSpan AutoRetryDelay { get; set; }
}

El código siguiente compila la raíz de la configuración, enlaza una sección al tipo de clase TransientFaultHandlingOptions e imprime los valores enlazados en la ventana de la consola:

IConfigurationRoot configurationRoot = configuration.Build();

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

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

La aplicación escribiría la siguiente salida de ejemplo:

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

Proveedor de configuración XML

La clase XmlConfigurationProvider carga la configuración desde un archivo XML en tiempo de ejecución. Instale el paquete NuGet Microsoft.Extensions.Configuration.Xml.

En el código siguiente se muestra la configuración de archivos XML mediante el proveedor de configuración XML.

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

namespace ConsoleXml.Example;

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

        // Application code should start here.

        await host.RunAsync();
    }

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

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

                configuration.AddEnvironmentVariables();

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

El código anterior:

  • Borra todos los proveedores de configuración existentes que se agregaron de forma predeterminada en el método CreateDefaultBuilder(String[]).
  • Configura el proveedor de configuración XML para cargar los archivos appsettings.xml y repeating-example.xml con las siguientes opciones:
    • optional: true: el archivo es opcional.
    • reloadOnChange: true: el archivo se recarga cuando se guardan los cambios.
  • Configura el proveedor de configuración de variables de entorno.
  • Configura el proveedor de configuración de línea de comandos si el valor args especificado contiene argumentos.

La configuración XML se reemplaza por la configuración del proveedor de configuración de variables de entorno y del proveedor de configuración de línea de comandos.

A continuación se muestra un ejemplo de archivo appsettings.xml con varios valores de configuración:

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

En .NET 5 y versiones anteriores, agregue el atributo name para distinguir los elementos repetitivos que usan el mismo nombre de elemento. En .NET 6 y versiones posteriores, el proveedor de configuración XML indexa automáticamente los elementos repetitivos. Eso significa que no tiene que especificar el atributo name, salvo si quiere el índice "0" en la clave y solo hay un elemento.

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

El código siguiente lee el archivo de configuración anterior y muestra las claves y los valores:

IConfigurationRoot configurationRoot = configuration.Build();

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

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

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

La aplicación escribiría la siguiente salida de ejemplo:

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

Los atributos se pueden usar para suministrar valores:

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

El archivo de configuración anterior carga las siguientes claves con value:

  • key:attribute
  • section:key:attribute

Proveedor de configuración INI

La clase IniConfigurationProvider carga la configuración desde un archivo INI en tiempo de ejecución. Instale el paquete NuGet Microsoft.Extensions.Configuration.Ini.

En el código siguiente se borran todos los proveedores de configuración y se agregan los IniConfigurationProvider con dos archivos INI como origen:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

namespace ConsoleIni.Example;

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

        // Application code should start here.

        await host.RunAsync();
    }

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

                IHostEnvironment env = hostingContext.HostingEnvironment;

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

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

A continuación se muestra un ejemplo de archivo appsettings.ini con varios valores de configuración:

SecretKey="Secret key value"

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

[Logging:LogLevel]
Default=Information
Microsoft=Warning

En el código siguiente se muestran los valores de configuración anteriores escribiéndolo en la ventana de la consola:

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

La aplicación escribiría la siguiente salida de ejemplo:

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

Proveedor de configuración de variables de entorno

Al usar la configuración predeterminada, EnvironmentVariablesConfigurationProvider carga la configuración de los pares clave-valor de la variable de entorno después de leer appsettings.json, appsettings. Environment .json y el Administrador de secretos. Por lo tanto, los valores de clave que se leen del entorno reemplazan los valores que se leen de appsettings.json, appsettings. Environment .json y del administrador de secretos.

El separador : no funciona con claves jerárquicas de variables de entorno en todas las plataformas. Todas las plataformas admiten un carácter de subrayado doble (__), que se reemplaza automáticamente por un signo :. Por ejemplo, el separador : no es compatible con Bash, pero __ sí.

Los siguientes comandos set:

  • Establecen las claves de entorno y los valores del ejemplo anterior en Windows.
  • Pruebe la configuración cambiando sus valores predeterminados. El comando dotnet run debe ejecutarse en el directorio del proyecto.
set SecretKey="Secret key from environment"
set TransientFaultHandlingOptions__Enabled="true"
set TransientFaultHandlingOptions__AutoRetryDelay="00:00:13"

dotnet run

Los ajustes de configuración del entorno anteriores:

  • Solo se establecen en procesos iniciados desde la ventana de comandos en la que se establecieron.
  • No los podrán leer las aplicaciones web que se inician con Visual Studio.

Con Visual Studio 2019 16.10, versión preliminar 4 y posteriores, puede especificar variables de entorno mediante el cuadro de diálogo Launch Profiles (Iniciar perfiles).

Cuadro de diálogo Launch Profiles (Iniciar perfiles) con variables de entorno

Los siguientes comandos setx se pueden usar para establecer las claves de entorno y los valores en Windows. A diferencia de set, la configuración de setx se conserva. /M establece la variable en el entorno del sistema. Si no se usa el modificador /M, se establece una variable de entorno de usuario.

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

dotnet run

Para comprobar que los comandos anteriores invalidan appsettings.json y appsettings. Environment .json:

  • Con Visual Studio: salga y reinicie Visual Studio.
  • Con la CLI: abra una nueva ventana de comandos y escriba dotnet run.

Llame a AddEnvironmentVariables con una cadena para especificar un prefijo para las variables de entorno:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

namespace ConsoleEnvironment.Example;

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

        // Application code should start here.

        await host.RunAsync();
    }

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

En el código anterior:

  • config.AddEnvironmentVariables(prefix: "CustomPrefix_") se agrega después de los proveedores de configuración predeterminados. Para obtener un ejemplo de ordenación de los proveedores de configuración, consulte Proveedor de configuración XML.
  • Las variables de entorno establecidas con el prefijo CustomPrefix_ invalidan los proveedores de configuración predeterminados. Esto incluye las variables de entorno sin el prefijo.

El prefijo se quita cuando se leen los pares clave-valor de configuración.

Los siguientes comandos prueban el prefijo personalizado:

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

dotnet run

La configuración predeterminada carga las variables de entorno y los argumentos de la línea de comandos con el prefijo DOTNET_. .NET usa el prefijo DOTNET_ para la configuración del host y la configuración de la aplicación, pero no para la del usuario.

Para obtener más información sobre la configuración del host y de la aplicación, consulte el artículo Host genérico de .NET.

En Azure App Service, seleccione Nueva configuración de la aplicación en la página Configuración > Configuración. Los ajustes de configuración de Azure App Service:

  • Se cifran en reposo y se transmiten a través de un canal cifrado.
  • Se exponen como variables de entorno.

Prefijos de cadena de conexión

La API de configuración tiene reglas de procesamiento especiales para cuatro variables de entorno de cadena de conexión. Estas cadenas de conexión están implicadas en la configuración de las cadenas de conexión de Azure para el entorno de la aplicación. Las variables de entorno con los prefijos que se muestran en la tabla se cargan en la aplicación con la configuración predeterminada o cuando no se proporciona ningún prefijo a AddEnvironmentVariables.

Prefijo de cadena de conexión Proveedor
CUSTOMCONNSTR_ Proveedor personalizado
MYSQLCONNSTR_ MySQL
SQLAZURECONNSTR_ Azure SQL Database
SQLCONNSTR_ SQL Server

Cuando una variable de entorno se detecta y carga en la configuración con cualquiera de los cuatro prefijos que se muestran en la tabla:

  • La clave de configuración se crea al quitar el prefijo de la variable de entorno y al agregar una sección de clave de configuración (ConnectionStrings).
  • Se crea un nuevo par clave-valor de configuración que representa el proveedor de conexión de base de datos (excepto para CUSTOMCONNSTR_, que no tiene ningún proveedor indicado).
Clave de variable de entorno Clave de configuración convertida Entrada de configuración del proveedor
CUSTOMCONNSTR_{KEY} ConnectionStrings:{KEY} Entrada de configuración no creada.
MYSQLCONNSTR_{KEY} ConnectionStrings:{KEY} Clave: ConnectionStrings:{KEY}_ProviderName:
Valor: MySql.Data.MySqlClient
SQLAZURECONNSTR_{KEY} ConnectionStrings:{KEY} Clave: ConnectionStrings:{KEY}_ProviderName:
Valor: System.Data.SqlClient
SQLCONNSTR_{KEY} ConnectionStrings:{KEY} Clave: ConnectionStrings:{KEY}_ProviderName:
Valor: System.Data.SqlClient

Variables de entorno configuradas en launchSettings.json

Las variables de entorno configuradas en launchSettings.json invalidan aquellas configuradas en el entorno del sistema.

Proveedor de configuración de línea de comandos

Si se usa la configuración predeterminada, CommandLineConfigurationProvider carga la configuración de los pares de clave-valor de argumento de la línea de comandos después de los siguientes orígenes de configuración:

  • Archivos appsettings.json y appsettings.Environment.json.
  • Secretos de aplicación (administrador de secretos) en el entorno Development.
  • Variables de entorno.

De forma predeterminada, los valores de configuración establecidos en la línea de comandos reemplazan los valores de configuración establecidos con el resto de proveedores de configuración.

Con Visual Studio 2019 16.10, versión preliminar 4 y posteriores, puede especificar argumentos de la línea de comandos mediante el cuadro de diálogo Launch Profiles (Iniciar perfiles).

Cuadro de diálogo Launch Profiles (Iniciar perfiles) con argumentos de la línea de comandos

Argumentos de la línea de comandos

El comando siguiente establece las claves y los valores mediante =:

dotnet run SecretKey="Secret key from command line"

El comando siguiente establece las claves y los valores mediante /:

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

El comando siguiente establece las claves y los valores mediante --:

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

El valor de la clave:

  • Debe seguir a un signo =, o bien la clave debe tener un prefijo -- o / cuando el valor sigue a un espacio.
  • No es necesario si se usa =. Por ejemplo: SomeKey=.

Dentro del mismo comando, no mezcle pares clave-valor de argumento de la línea de comandos que usan = con pares de clave-valor que usan un espacio.

Proveedor de configuración de clave por archivo

KeyPerFileConfigurationProvider usa los archivos de un directorio como pares clave-valor de configuración. La clave es el nombre de archivo. El valor es el contenido del archivo. El proveedor de configuración de clave por archivo se usa en escenarios de hospedaje de Docker.

Para activar la configuración de clave por archivo, llame al método de extensión AddKeyPerFile en una instancia de ConfigurationBuilder. La ruta de acceso directoryPath a los archivos debe ser una ruta de acceso absoluta.

Las sobrecargas permiten especificar:

  • Un delegado Action<KeyPerFileConfigurationSource> que configura el origen.
  • Si el directorio es opcional y la ruta de acceso al directorio.

El carácter de subrayado doble (__) se usa como delimitador de claves de configuración en los nombres de archivo. Por ejemplo, el nombre de archivo Logging__LogLevel__System genera la clave de configuración Logging:LogLevel:System.

Llame a ConfigureAppConfiguration cuando cree el host para especificar la configuración de la aplicación:

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

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

Proveedor de configuración de memoria

MemoryConfigurationProvider usa una colección en memoria como pares clave-valor de configuración.

El código siguiente agrega una colección en memoria al sistema de configuración:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

namespace ConsoleMemory.Example;

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

        // Application code should start here.

        await host.RunAsync();
    }

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

En el código anterior, MemoryConfigurationBuilderExtensions.AddInMemoryCollection(IConfigurationBuilder, IEnumerable<KeyValuePair<String,String>>) agrega el proveedor de memoria después de los proveedores de configuración predeterminados. Para obtener un ejemplo de ordenación de los proveedores de configuración, consulte Proveedor de configuración XML.

Vea también