Configuración en ASP.NET Core

Por Rick Anderson y Kirk Larkin

La configuración de aplicaciones en ASP.NET Core se realiza mediante uno o varios proveedores de configuración. Los proveedores de configuración leen los datos sobre los ajustes de los pares clave-valor mediante distintos orígenes de configuración:

  • Archivos de configuración, como appsettings.json
  • Variables de entorno
  • Azure Key Vault
  • Configuración de aplicaciones de Azure
  • Argumentos de la línea de comandos
  • Proveedores personalizados (instalados o creados)
  • Archivos de directorio
  • Objetos de .NET en memoria

En este artículo se proporciona información sobre la configuración en ASP.NET Core. Para más información sobre el uso de la configuración en las aplicaciones de consola, consulte Configuración de .NET.

Configuración de host y de aplicación

Las aplicaciones de ASP.NET Core configuran e inician un host. El host es responsable de la administración del inicio y la duración de la aplicación. Las plantillas de ASP.NET Core crean un objeto WebApplicationBuilder que contiene el host. Aunque parte de la configuración se puede realizar tanto en los proveedores de configuración tanto del host como de la aplicación, por lo general la configuración necesaria para el host solo se debe realizar en la configuración del host.

La configuración de la aplicación tiene la máxima prioridad y se detalla en la sección siguiente. La configuración del host sigue a la configuración de la aplicación y se describe en este artículo.

Orígenes de configuración de aplicación predeterminados

Las aplicaciones web de ASP.NET Core creadas con dotnet new o con Visual Studio generan el código siguiente:

var builder = WebApplication.CreateBuilder(args);

WebApplication.CreateBuilder inicializa una nueva instancia de la clase WebApplicationBuilder con valores predeterminados preconfigurados. El objeto WebApplicationBuilder (builder) inicializado proporciona la configuración predeterminada de la aplicación en el orden siguiente, de la prioridad más alta a la más baja:

  1. Argumentos de la línea de comandos con el proveedor de configuración de línea de comandos.
  2. Variables de entorno sin prefijo que usan el proveedor de configuración de variables de entorno sin prefijo
  3. Secretos del usuario cuando la aplicación se ejecuta en el entorno .
  4. appsettings.{Environment}.json que usa el proveedor de configuración JSON Por ejemplo, appsettings.Production.json y appsettings.Development.json.
  5. appsettings.json que usa el proveedor de configuración JSON
  6. Una reserva a la configuración del host (se describe en la siguiente sección)

Orígenes de configuración de host predeterminados

La siguiente lista contiene los orígenes de configuración de host predeterminados, de la prioridad más alta a la más baja:

  1. Variables de entorno con el prefijo ASPNETCORE_ que usan el proveedor de configuración de variables de entorno
  2. Argumentos de la línea de comandos con el proveedor de configuración de línea de comandos
  3. Variables de entorno con el prefijo DOTNET_ que usan el proveedor de configuración de variables de entorno

Si se establece un valor de configuración en la configuración del host y de la aplicación, se usa la configuración de la aplicación.

Consulte la explicación en este comentario de GitHub para saber por qué en la configuración del host las variables de entorno con prefijo ASPNETCORE_ tienen mayor prioridad que los argumentos de la línea de comandos.

Variables de host

Las siguientes variables se bloquean pronto al inicializar los generadores de hosts y no se ven influidas por la configuración de la aplicación:

Cualquier otra configuración de host se lee de la configuración de la aplicación en lugar de la configuración del host.

URLS es una de las muchas configuraciones de host comunes que no es una configuración de arranque. Como cualquier otra configuración de host que no figura en la lista anterior, URLS se lee más adelante desde la configuración de la aplicación. La configuración del host es una reserva de la configuración de la aplicación, con lo cual se puede usar para establecer URLS, pero quedará invalidada por cualquier origen de configuración de la aplicación, como appsettings.json.

Para obtener más información, consulte Cambio de la raíz del contenido, el nombre de la aplicación y el entorno y Cambio de la raíz del contenido, el nombre de la aplicación y el entorno por variables de entorno o línea de comandos.

El resto de secciones de este artículo se centran en la configuración de la aplicación.

Proveedores de configuración de la aplicación

El código siguiente muestra los proveedores de configuración habilitados en el orden en el que se han agregado:

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

La lista anterior de orígenes de configuración predeterminados ordenados de prioridad más alta a más baja muestra los proveedores en orden opuesto al que se agregan a la aplicación generada por la plantilla. Así, por ejemplo, el proveedor de configuración JSON se agrega antes que el proveedor de configuración de línea de comandos.

Los proveedores de configuración que se agreguen posteriormente tienen mayor prioridad e invalidan los ajustes de configuración de clave anteriores. Por ejemplo, si MyKey se establece tanto en appsettings.json como en el entorno, se usará el valor del entorno. Con los proveedores de configuración predeterminados, el proveedor de configuración de línea de comandos reemplaza al resto de proveedores.

Para obtener más información sobre CreateBuilder, consulte el artículo Configuración predeterminada del generador.

appsettings.json

Fíjese en el siguiente archivo appsettings.json :

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

El siguiente código de la descarga de ejemplo muestra algunas de las configuraciones anteriores:

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

El elemento JsonConfigurationProvider predeterminado carga la configuración en el siguiente orden:

  1. appsettings.json
  2. appsettings.{Environment}.json: por ejemplo, los archivos appsettings.Production.json y appsettings.Development.json. La versión del entorno del archivo se carga en función de IHostingEnvironment.EnvironmentName. Para obtener más información, consulte Usar varios entornos en ASP.NET Core.

Los valores de appsettings.{Environment}.json invalidan las claves en appsettings.json. Por ejemplo, de forma predeterminada:

  • En la fase de desarrollo, la configuración appsettings.Development.json sobrescribe los valores encontrados en appsettings.json.
  • En la fase de producción, la configuración appsettings.Production.json sobrescribe los valores encontrados en appsettings.json. Por ejemplo, al implementar la aplicación en Azure.

Si se debe garantizar un valor de configuración, consulte GetValue. En el ejemplo anterior solo se leen cadenas y no se admite un valor predeterminado.

Si usa la configuración predeterminada, los archivosappsettings.json y appsettings.{Environment}.json están habilitados con reloadOnChange: true. Los cambios realizados en los archivos appsettings.json y appsettings.{Environment}.jsondespués de que la aplicación se inicie los lee el proveedor de configuración JSON.

Enlace de datos de configuración jerárquica mediante el patrón de opciones

La mejor manera de leer valores de configuración relacionados es usar el patrón de opciones. Por ejemplo, para leer los siguientes valores de configuración:

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

Cree la siguiente clase PositionOptions:

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

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

Una clase de opciones:

  • Debe ser no abstracta con un constructor público sin parámetros.
  • Todas las propiedades de lectura y escritura públicas del tipo están enlazadas.
  • Los campos no se enlazan. En el código anterior, Position no está enlazado. El campo Position se usa para que la cadena "Position" no se tenga que codificar de forma rígida en la aplicación al enlazar la clase a un proveedor de configuración.

El código siguiente:

  • Llama a ConfigurationBinder.Bind para enlazar la clase PositionOptions a la sección Position.
  • Muestra los datos de configuración de 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}");
    }
}

En el código anterior, de forma predeterminada, los cambios en el archivo de configuración de JSON producidos una vez iniciada la aplicación se leen.

ConfigurationBinder.Get<T> enlaza y devuelve el tipo especificado. Puede ser más conveniente usar ConfigurationBinder.Get<T> que ConfigurationBinder.Bind. En el código siguiente se muestra cómo puede usar ConfigurationBinder.Get<T> con la clase 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}");
    }
}

En el código anterior, de forma predeterminada, los cambios en el archivo de configuración de JSON producidos una vez iniciada la aplicación se leen.

Un enfoque alternativo a la hora de usar el patrón de opciones consiste en enlazar la sección Position y agregarla al contenedor del servicio de inserción de dependencias. En el siguiente código se agrega PositionOptions al contenedor de servicios con Configure y se enlaza a la configuración:

using ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

A partir del código anterior, el siguiente código lee las opciones de posición:

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

En el código anterior, los cambios en el archivo de configuración JSON producidos una vez iniciada la aplicación no se leen. Para leer los cambios una vez iniciada la aplicación, use IOptionsSnapshot.

Si usa la configuración predeterminada, los archivosappsettings.json y appsettings.{Environment}.json están habilitados con reloadOnChange: true. Los cambios realizados en los archivos appsettings.json y appsettings.{Environment}.jsondespués de que la aplicación se inicie los lee el proveedor de configuración JSON.

Consulte la sección Proveedor de configuración JSJSON de este documento para obtener información sobre cómo agregar más archivos de configuración JSON.

Combinación de colecciones de servicios

Tenga en cuenta el siguiente método que registra los servicios y configura las opciones:

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

Los grupos de registros relacionados pueden moverse a un método de extensión para registrar los servicios. Por ejemplo, los servicios de configuración se agregan a la siguiente clase:

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

Los servicios restantes se registran en una clase similar. El siguiente código usa los nuevos métodos de extensión para registrar los servicios:

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: Cada método de extensión services.Add{GROUP_NAME} agrega servicios y potencialmente los configura. Por ejemplo, AddControllersWithViews agrega los controladores MVC de servicios con las vistas que se requieren y AddRazorPages agrega los servicios que Razor Pages requiere.

Seguridad y secretos de usuario

Directrices para los datos de configuración:

  • Nunca almacene contraseñas u otros datos confidenciales en el código del proveedor de configuración o en archivos de configuración de texto sin formato. Se puede usar la herramienta Administrador de secretos para almacenar secretos en desarrollo.
  • No use secretos de producción en los entornos de desarrollo o pruebas.
  • Especifique los secretos fuera del proyecto para que no se confirmen en un repositorio de código fuente de manera accidental.

De forma predeterminada, el origen de configuración de los secretos de usuario se registra después de los orígenes de configuración JSON. Por lo tanto, las claves de secretos de usuario tienen prioridad sobre las claves de appsettings.json y appsettings.{Environment}.json.

Para obtener más información sobre cómo almacenar contraseñas u otros datos confidenciales consulte:

Azure Key Vault almacena de forma segura secretos de aplicación para aplicaciones de ASP.NET Core. Para obtener más información, vea Proveedor de configuración de Azure Key Vault en ASP.NET Core.

Variables de entorno sin prefijo

Las variables de entorno sin prefijo son variables de entorno distintas de las que exhiben los prefijos ASPNETCORE_ o DOTNET_. Por ejemplo, las plantillas de aplicación web de ASP.NET Core establecen "ASPNETCORE_ENVIRONMENT": "Development" en launchSettings.json. Para obtener más información sobre las variables de entorno ASPNETCORE_ y DOTNET_, consulte:

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 los secretos de usuario. 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 los secretos de usuario.

El separador : no funciona con claves jerárquicas de variables de entorno en todas las plataformas. __, el carácter de subrayado doble, tiene las siguientes características:

  • Es compatible con todas las plataformas. Por ejemplo, el separador : no es compatible con Bash, pero __ sí.
  • Se reemplaza automáticamente por un signo :.

Los siguientes comandos set:

  • Establecen las claves de entorno y los valores del ejemplo anterior en Windows.
  • Prueban la configuración al usar la descarga de ejemplo. El comando dotnet run debe ejecutarse en el directorio del proyecto.
set MyKey="My key from Environment"
set Position__Title=Environment_Editor
set Position__Name=Environment_Rick
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 los exploradores que se inician con Visual Studio.

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

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:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

En el código anterior:

  • builder.Configuration.AddEnvironmentVariables(prefix: "MyCustomPrefix_") 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 la sección Proveedor de configuración JSON.
  • Las variables de entorno establecidas con el prefijo MyCustomPrefix_ 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 MyCustomPrefix_MyKey="My key with MyCustomPrefix_ Environment"
set MyCustomPrefix_Position__Title=Editor_with_customPrefix
set MyCustomPrefix_Position__Name=Environment_Rick_cp
dotnet run

La configuración predeterminada carga las variables de entorno y los argumentos de la línea de comandos con los prefijos DOTNET_ y ASPNETCORE_. ASP.NET Core usa los prefijos DOTNET_ y ASPNETCORE_ para la configuración del host y 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.

Para más información, consulte Aplicaciones de Azure: Invalidación de la configuración de la aplicación mediante Azure Portal.

Consulte la sección Prefijos de cadena de conexión para obtener información sobre las cadenas de conexión de base de datos de Azure.

Nomenclatura de variables de entorno

Los nombres de las variables de entorno reflejan la estructura de un archivo appsettings.json . Cada elemento de la jerarquía está separado por un carácter de subrayado doble (preferible) o un signo de dos puntos. Cuando la estructura del elemento incluye una matriz, el índice de la matriz se debe tratar como un nombre de elemento adicional en esta ruta de acceso. Considere el siguiente archivo appsettings.json y sus valores equivalentes representados como variables de entorno.

appsettings.json

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

variables de entorno

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

Variables de entorno configuradas en el archivo launchSettings.json generado

Las variables de entorno configuradas en launchSettings.json invalidan aquellas configuradas en el entorno del sistema. Por ejemplo, las plantillas web ASP.NET Core generan un archivo launchSettings.json que establece la configuración del punto de conexión en:

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

Al configurar applicationUrl, se establece la variable de entorno ASPNETCORE_URLS y se invalidan los valores establecidos en el entorno.

Variables de entorno de escape en Linux

En Linux, el valor de las variables de entorno de URL debe ser de escape, para que systemd pueda analizarlas. Uso de la herramienta de Linux systemd-escape que produce http:--localhost:5001

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

Visualización de las variables de entorno

En el código siguiente se muestran las variables de entorno y los valores en el inicio de la aplicación, lo que puede resultar útil al depurar la configuración del entorno:

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

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

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 aplicaciones en el entorno de desarrollo.
  • 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.

Argumentos de la línea de comandos

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

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

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

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

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

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

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

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.

Asignaciones de modificador

Las asignaciones de modificador admiten la lógica de sustitución de nombres de clave. Proporcione un diccionario de reemplazos de modificador al método AddCommandLine.

Cuando se usa el diccionario de asignaciones de modificador, se comprueba en el diccionario si una clave coincide con la clave proporcionada por un argumento de línea de comandos. Si la clave de la línea de comandos se encuentra en el diccionario, se devuelve el valor del diccionario para establecer el par clave-valor en la configuración de la aplicación. Se requiere una asignación de conmutador para cualquier clave de línea de comandos precedida por un solo guion (-).

Reglas de clave del diccionario de asignaciones de modificador:

  • Los modificadores deben comenzar con - o --.
  • El diccionario de asignaciones de modificador no debe contener claves duplicadas.

Para usar un diccionario de asignaciones de modificador, páselo a la llamada 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();

La ejecución del siguiente comando sirve para probar el reemplazo de claves:

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

El código siguiente muestra los valores de clave para las claves reemplazadas:

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

En el caso de las aplicaciones que usen las asignaciones de modificador, la llamada a CreateDefaultBuilder no tiene que pasar argumentos. En la llamada de AddCommandLine al método CreateDefaultBuilder, no se incluyen modificadores asignados y no hay forma de pasar el diccionario de asignación de modificador a CreateDefaultBuilder. La solución no es pasar los argumentos de CreateDefaultBuilder, sino permitir que el método AddCommandLine del método ConfigurationBuilder procese tanto los argumentos como el diccionario de asignación de modificador.

Configuración del entorno y de los argumentos de la línea de comandos con Visual Studio

Los argumentos de entorno y de línea de comandos se pueden establecer en Visual Studio desde el cuadro de diálogo de perfiles de inicio:

  • En el Explorador de soluciones, haga clic con el botón derecho en el proyecto y seleccione Propiedades.
  • Seleccione la pestaña Depurar > General y luego Abrir la interfaz de usuario de perfiles de inicio de depuración.

Datos de configuración jerárquica

La API de configuración lee los datos de configuración jerárquica al disminuir los datos jerárquicos mediante el uso de un delimitador en las claves de configuración.

La descarga de ejemplo contiene el siguiente archivo appsettings.json:

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

El siguiente código de la descarga de ejemplo muestra algunas de las opciones de configuración:

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 mejor manera de leer datos de configuración jerárquica es usar el patrón de opciones. Para obtener más información, vea la sección Enlace de datos de configuración jerárquica en este documento.

Los métodos GetSection y GetChildren están disponibles para aislar las secciones y los elementos secundarios de una sección en los datos de configuración. Estos métodos se describen más adelante en la sección GetSection, GetChildren y Exists.

Claves y valores de configuración

Las claves de configuración:

  • No distinguen mayúsculas de minúsculas. Por ejemplo, ConnectionString y connectionstring se consideran claves equivalente.
  • Si se establece una clave y un valor en más de un proveedor de configuración, se usa el valor del último proveedor agregado. Para obtener más información, vea la sección Configuración predeterminada.
  • Claves jerárquicas
    • Dentro de la API de configuración, un separador de dos puntos (:) funciona en todas las plataformas.
    • En las variables de entorno, puede que un separador de dos puntos no funcione en todas las plataformas. Todas las plataformas admiten un carácter de subrayado doble, __, que se convierte automáticamente en un signo de dos puntos :.
    • En Azure Key Vault, las claves jerárquicas usan -- como separador. El proveedor de configuración de Azure Key Vault reemplaza automáticamente -- con : cuando los secretos se cargan en la configuración de la aplicación.
  • ConfigurationBinder admite enlazar matrices a objetos con los índices de matriz en las claves de configuración. El enlace de matriz se describe en la sección Enlace de una matriz a una clase.

Los valores de configuración:

  • Son cadenas.
  • Los valores NULL no se pueden almacenar en la configuración ni enlazar a los objetos.

Proveedores de configuración

La siguiente tabla muestra los proveedores de configuración disponibles para las aplicaciones de ASP.NET Core.

Proveedor Proporciona la configuración de
Proveedor de configuración de Azure Key Vault Azure Key Vault
Proveedor de configuración de aplicaciones de Azure Configuración de aplicaciones de Azure
Proveedor de configuración de línea de comandos Parámetros de la línea de comandos
Proveedor de configuración personalizada Origen personalizado
Proveedor de configuración de variables de entorno Variables de entorno
Proveedor de configuración de archivo Archivos INI, JSON y XML
Proveedor de configuración de clave por archivo Archivos de directorio
Proveedor de configuración de memoria Colecciones en memoria
Secretos de usuario Archivo en el directorio del perfil de usuario

Los orígenes de configuración se leen en el orden en que se especifican sus proveedores de configuración. Ordene los proveedores de configuración en el código para cumplir con las prioridades relacionadas con los orígenes de configuración subyacentes que la aplicación necesita.

Esta es una secuencia típica de proveedores de configuración:

  1. appsettings.json
  2. appsettings.{Environment}.json
  3. Secretos de usuario
  4. Variables de entorno con el proveedor de configuración de variables de entorno.
  5. Argumentos de la línea de comandos con el proveedor de configuración de línea de comandos.

Una práctica común es agregar el proveedor de configuración de línea de comandos al final en una serie de proveedores para permitir que los argumentos de la línea de comandos reemplacen la configuración establecida por el resto de los proveedores.

La secuencia de proveedores anterior se usa en la configuración predeterminada.

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

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 INI

IniConfigurationProvider carga la configuración desde pares clave-valor de archivo INI en tiempo de ejecución.

El código siguiente borra todos los proveedores de configuración y agrega varios:

var builder = WebApplication.CreateBuilder(args);

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

    var env = hostingContext.HostingEnvironment;

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

    config.AddEnvironmentVariables();

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

builder.Services.AddRazorPages();

var app = builder.Build();

En el código anterior, la configuración de los archivos MyIniConfig.ini y MyIniConfig.{Environment}.ini se reemplaza por la configuración de:

La descarga de ejemplo contiene el siguiente archivo MyIniConfig.ini:

MyKey="MyIniConfig.ini Value"

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

[Logging:LogLevel]
Default=Information
Microsoft=Warning

El siguiente código de la descarga de ejemplo muestra algunas de las configuraciones anteriores:

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

Proveedor de configuraciónJSON

JsonConfigurationProvider carga la configuración desde pares clave-valor de archivos 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.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

El código anterior:

Por lo general, no conviene que un archivo JSON personalizado invalide los valores establecidos en el proveedor de configuración de variables de entorno ni en el proveedor de configuración de línea de comandos.

Proveedor de configuración XML

XmlConfigurationProvider carga la configuración desde pares clave-valor de archivo XML en tiempo de ejecución.

El código siguiente borra todos los proveedores de configuración y agrega varios:

var builder = WebApplication.CreateBuilder(args);

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

    var env = hostingContext.HostingEnvironment;

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

    config.AddEnvironmentVariables();

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

builder.Services.AddRazorPages();

var app = builder.Build();

En el código anterior, la configuración de los archivos MyXMLFile.xml y MyXMLFile.{Environment}.xml se reemplaza por la configuración de:

La descarga de ejemplo contiene el siguiente archivo MyXMLFile.xml:

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

El siguiente código de la descarga de ejemplo muestra algunas de las configuraciones anteriores:

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

Los elementos de repetición que usan el mismo nombre de elemento funcionan si el atributo name se usa para distinguir los elementos:

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

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

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 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 contiene 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((hostingContext, config) =>
{
    var path = Path.Combine(
        Directory.GetCurrentDirectory(), "path/to/files");
    config.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:

var builder = WebApplication.CreateBuilder(args);

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

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

    config.AddInMemoryCollection(Dict);

    config.AddEnvironmentVariables();

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

builder.Services.AddRazorPages();

var app = builder.Build();

El siguiente código de la descarga de ejemplo muestra las opciones de configuración anteriores:

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

En el código anterior, config.AddInMemoryCollection(Dict) 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 la sección Proveedor de configuración JSON.

Consulte la sección Enlace de matrices para ver otro ejemplo que usa MemoryConfigurationProvider.

Configuración del punto de conexión de Kestrel

La configuración del punto de conexión específico de Kestrel invalida todas las configuraciones del punto de conexión entre servidores. Las configuraciones del punto de conexión entre servidores incluyen:

Tenga en cuenta el archivo siguiente appsettings.json usado en una aplicación web de ASP.NET Core:

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

Cuando el marcado resaltado anterior se usa en una aplicación web de ASP.NET Core y la aplicación se inicia en la línea de comandos con la siguiente configuración del punto de conexión entre servidores:

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

Kestrel se enlaza con el punto de conexión configurado específicamente para Kestrel en el archivo appsettings.json (https://localhost:9999) y no https://localhost:7777.

Considere el punto de conexión específico de Kestrel configurado como una variable de entorno:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

En la variable de entorno anterior, Https es el nombre del punto de conexión específico de Kestrel. En el archivo appsettings.json anterior también se define un punto de conexión específico de Kestrel denominado Https. De manera predeterminada, las variables de entorno que utilizan el proveedor de configuración de variables de entorno se leen después de appsettings.{Environment}.json, por lo tanto, la variable de entorno anterior se usa para el punto de conexión Https.

GetValue

ConfigurationBinder.GetValue extrae un único valor de la configuración con una clave determinada y lo convierte al tipo especificado:

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

En el código anterior, si NumberKey no se encuentra en la configuración, se usa el valor predeterminado de 99.

GetSection, GetChildren y Exists

Para los ejemplos siguientes, considere el siguiente archivo MySubsection.json:

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

El código siguiente agrega MySubsection.json a los proveedores de configuración:

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

GetSection

IConfiguration.GetSection devuelve una subsección de la configuración con la clave de subsección especificada.

El código siguiente devuelve los valores de 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"]}'");
    }
}

El código siguiente devuelve los valores de 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 nunca devuelve null. Si no se encuentra una sección que coincida, se devuelve una IConfigurationSection vacía.

Cuando GetSection devuelve una sección coincidente, Value no se rellena. Se devuelven Key y Path si la sección existe.

GetChildren y Exists

El código siguiente llama a IConfiguration.GetChildren y devuelve los valores de 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);
    }
}

El código anterior llama a ConfigurationExtensions.Exists para comprobar que la sección existe:

Enlace de matrices

ConfigurationBinder.Bind admite enlazar matrices a objetos con los índices de matriz en las claves de configuración. Cualquier formato de matriz que exponga un segmento de clave numérica es capaz de enlazar una matriz a una matriz de clase POCO.

Tenga en cuenta este archivo MyArray.json de la descarga de ejemplo:

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

El código siguiente agrega MyArray.json a los proveedores de configuración:

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

El código siguiente lee la configuración y muestra los valores:

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

El código anterior devuelve el siguiente resultado:

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

En el resultado anterior, el índice 3 tiene el valor value40, que corresponde a "4": "value40", en MyArray.json. Los índices de matriz enlazados son continuos y no están enlazados al índice de la clave de configuración. El enlazador de configuración no es capaz de enlazar los valores NULL ni de crear entradas NULL en objetos enlazados.

Proveedores de configuración personalizada

La aplicación de ejemplo muestra cómo crear un proveedor de configuración básica que lee los pares clave-valor de configuración desde una base de datos mediante Entity Framework (EF).

El proveedor tiene las siguientes características:

  • La base de datos en memoria de EF se usa para fines de demostración. Para usar una base de datos que requiere una cadena de conexión, implemente un ConfigurationBuilder secundario para suministrar la cadena de conexión desde otro proveedor de configuración.
  • El proveedor lee una tabla de base de datos en la configuración en el inicio. El proveedor no consulta la base de datos por clave.
  • La función de recarga en cambio no se implementa, por lo que actualizar la base de datos después del inicio de la aplicación no afecta a la configuración de la aplicación.

Defina una entidad EFConfigurationValue para almacenar los valores de configuración en la base de datos.

Models/EFConfigurationValue.cs:

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

Agregue un EFConfigurationContext para almacenar y tener acceso a los valores configurados.

EFConfigurationProvider/EFConfigurationContext.cs:

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

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

Cree una clase que implemente 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);
}

Cree el proveedor de configuración personalizado heredando de ConfigurationProvider. El proveedor de configuración inicializa la base de datos cuando está vacía. Puesto que las claves de configuración no distinguen entre mayúsculas y minúsculas, el diccionario empleado para iniciar la base de datos se crea con el comparador que tampoco hace tal distinción (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 método de extensión AddEFConfiguration permite agregar el origen de configuración 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));
    }
}

En el código siguiente se muestra cómo puede usar el EFConfigurationProvider personalizado en Program.cs:

//using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

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

var app = builder.Build();

app.Run();

Configuración de acceso con inserción de dependencias (DI)

La configuración se puede insertar en los servicios mediante la inserción de dependencias (DI) resolviendo el servicio IConfiguration:

public class Service
{
    private readonly IConfiguration _config;

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

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

        // ...
    }
}

Para obtener información sobre cómo acceder a valores mediante IConfiguration, vea GetValue y GetSection, GetChildren y Exists en este artículo.

Acceso a la configuración en Razor Pages

En el código siguiente se muestran los datos de configuración en una página de RazorPages:

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

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

En el siguiente código se agrega MyOptions al contenedor de servicios con Configure y se enlaza a la configuración:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

En el marcado siguiente se usa la directiva @injectRazor para resolver y mostrar los valores de las opciones:

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

Acceso a la configuración en un archivo de vista de MVC

En el código siguiente se muestran los datos de configuración de una vista de MVC:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

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

Acceder a la configuración en Program.cs

El código siguiente accede a la configuración en el archivo Program.cs.

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

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

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

app.Logger.LogInformation($"KeyOne = {key1}");
app.Logger.LogInformation($"KeyTwo = {key2}");

app.Run();

Configurar opciones con un delegado

Las opciones configuradas en un delegado invalidan los valores establecidos en los proveedores de configuración.

En el código siguiente, se agrega un servicio IConfigureOptions<TOptions> al contenedor de servicios. Usa un delegado para configurar los valores de 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();

En el código siguiente se muestran los valores de las opciones:

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

En el ejemplo anterior, los valores de Option1 y Option2 se especifican en appsettings.json y, luego, se reemplazan por el delegado configurado.

Configuración de host y de aplicación

Antes de configurar e iniciar la aplicación, se configura e inicia un host. El host es responsable de la administración del inicio y la duración de la aplicación. Tanto la aplicación como el host se configuran mediante los proveedores de configuración que se describen en este tema. Los pares clave-valor de configuración del host también se incluyen en la configuración de la aplicación. Para obtener más información sobre cómo se usan los proveedores de configuración cuando se compila el host y cómo afectan los orígenes de configuración a la configuración del host, consulte la información general sobre conceptos básicos de ASP.NET Core.

Configuración predeterminada del host

Para obtener más información sobre la configuración predeterminada al usar el host de web, vea la versión de este tema para ASP.NET Core 2.2.

  • La configuración del host la proporcionan los siguientes elementos:
  • La configuración predeterminada del host de web se ha establecido (ConfigureWebHostDefaults):
    • Kestrel se usa como el servidor web y se ha configurado mediante los proveedores de configuración de la aplicación.
    • Agregar el middleware de filtrado de host
    • Agregue el middleware de encabezados reenviados si la variable de entorno ASPNETCORE_FORWARDEDHEADERS_ENABLED se establece en true.
    • Habilite la integración con IIS.

Otra configuración

Este tema solo concierne a la configuración de aplicaciones. Otros aspectos de la ejecución y el hospedaje de aplicaciones ASP.NET Core se configuran mediante archivos de configuración que no se describen en este tema:

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

Para más información sobre cómo migrar la configuración de aplicaciones de versiones anteriores de ASP.NET, consulte Migrar de ASP.NET a ASP.NET Core.

Agregar configuración a partir de un ensamblado externo

Una implementación de IHostingStartup permite agregar mejoras a una aplicación al iniciarla a partir de un ensamblado externo fuera de la clase Startup de esta. Para obtener más información, consulte Uso de ensamblados de inicio de hospedaje en ASP.NET Core.

Recursos adicionales

La configuración de aplicaciones en ASP.NET Core se realiza mediante uno o varios proveedores de configuración. Los proveedores de configuración leen los datos sobre los ajustes de los pares clave-valor mediante distintos orígenes de configuración:

  • Archivos de configuración, como appsettings.json
  • Variables de entorno
  • Azure Key Vault
  • Configuración de aplicaciones de Azure
  • Argumentos de la línea de comandos
  • Proveedores personalizados (instalados o creados)
  • Archivos de directorio
  • Objetos de .NET en memoria

En este artículo se proporciona información sobre la configuración en ASP.NET Core. Para más información sobre el uso de la configuración en las aplicaciones de consola, consulte Configuración de .NET.

Configuración de host y de aplicación

Las aplicaciones de ASP.NET Core configuran e inician un host. El host es responsable de la administración del inicio y la duración de la aplicación. Las plantillas de ASP.NET Core crean un objeto WebApplicationBuilder que contiene el host. Aunque parte de la configuración se puede realizar tanto en los proveedores de configuración tanto del host como de la aplicación, por lo general la configuración necesaria para el host solo se debe realizar en la configuración del host.

La configuración de la aplicación tiene la máxima prioridad y se detalla en la sección siguiente. La configuración del host sigue a la configuración de la aplicación y se describe en este artículo.

Orígenes de configuración de aplicación predeterminados

Las aplicaciones web de ASP.NET Core creadas con dotnet new o con Visual Studio generan el código siguiente:

var builder = WebApplication.CreateBuilder(args);

WebApplication.CreateBuilder inicializa una nueva instancia de la clase WebApplicationBuilder con valores predeterminados preconfigurados. El objeto WebApplicationBuilder (builder) inicializado proporciona la configuración predeterminada de la aplicación en el orden siguiente, de la prioridad más alta a la más baja:

  1. Argumentos de la línea de comandos con el proveedor de configuración de línea de comandos.
  2. Variables de entorno sin prefijo que usan el proveedor de configuración de variables de entorno sin prefijo
  3. Secretos del usuario cuando la aplicación se ejecuta en el entorno .
  4. appsettings.{Environment}.json que usa el proveedor de configuración JSON Por ejemplo, appsettings.Production.json y appsettings.Development.json.
  5. appsettings.json que usa el proveedor de configuración JSON
  6. Una reserva a la configuración del host (se describe en la siguiente sección)

Orígenes de configuración de host predeterminados

La siguiente lista contiene los orígenes de configuración de host predeterminados, de la prioridad más alta a la más baja:

  1. Argumentos de la línea de comandos con el proveedor de configuración de línea de comandos
  2. Variables de entorno con el prefijo ASPNETCORE_ que usan el proveedor de configuración de variables de entorno
  3. Variables de entorno con el prefijo DOTNET_ que usan el proveedor de configuración de variables de entorno

Si se establece un valor de configuración en la configuración del host y de la aplicación, se usa la configuración de la aplicación.

Variables de host

Las siguientes variables se bloquean pronto al inicializar los generadores de hosts y no se ven influidas por la configuración de la aplicación:

Cualquier otra configuración de host se lee de la configuración de la aplicación en lugar de la configuración del host.

URLS es una de las muchas configuraciones de host comunes que no es una configuración de arranque. Como cualquier otra configuración de host que no figura en la lista anterior, URLS se lee más adelante desde la configuración de la aplicación. La configuración del host es una reserva de la configuración de la aplicación, con lo cual se puede usar para establecer URLS, pero quedará invalidada por cualquier origen de configuración de la aplicación, como appsettings.json.

Para obtener más información, consulte Cambio de la raíz del contenido, el nombre de la aplicación y el entorno y Cambio de la raíz del contenido, el nombre de la aplicación y el entorno por variables de entorno o línea de comandos.

El resto de secciones de este artículo se centran en la configuración de la aplicación.

Proveedores de configuración de la aplicación

El código siguiente muestra los proveedores de configuración habilitados en el orden en el que se han agregado:

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

La lista anterior de orígenes de configuración predeterminados ordenados de prioridad más alta a más baja muestra los proveedores en orden opuesto al que se agregan a la aplicación generada por la plantilla. Así, por ejemplo, el proveedor de configuración JSON se agrega antes que el proveedor de configuración de línea de comandos.

Los proveedores de configuración que se agreguen posteriormente tienen mayor prioridad e invalidan los ajustes de configuración de clave anteriores. Por ejemplo, si MyKey se establece tanto en appsettings.json como en el entorno, se usará el valor del entorno. Con los proveedores de configuración predeterminados, el proveedor de configuración de línea de comandos reemplaza al resto de proveedores.

Para obtener más información sobre CreateBuilder, consulte el artículo Configuración predeterminada del generador.

appsettings.json

Fíjese en el siguiente archivo appsettings.json :

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

El siguiente código de la descarga de ejemplo muestra algunas de las configuraciones anteriores:

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

El elemento JsonConfigurationProvider predeterminado carga la configuración en el siguiente orden:

  1. appsettings.json
  2. appsettings.{Environment}.json: por ejemplo, los archivos appsettings.Production.json y appsettings.Development.json. La versión del entorno del archivo se carga en función de IHostingEnvironment.EnvironmentName. Para obtener más información, consulte Usar varios entornos en ASP.NET Core.

Los valores de appsettings.{Environment}.json invalidan las claves en appsettings.json. Por ejemplo, de forma predeterminada:

  • En la fase de desarrollo, la configuración appsettings.Development.json sobrescribe los valores encontrados en appsettings.json.
  • En la fase de producción, la configuración appsettings.Production.json sobrescribe los valores encontrados en appsettings.json. Por ejemplo, al implementar la aplicación en Azure.

Si se debe garantizar un valor de configuración, consulte GetValue. En el ejemplo anterior solo se leen cadenas y no se admite un valor predeterminado.

Si usa la configuración predeterminada, los archivosappsettings.json y appsettings.{Environment}.json están habilitados con reloadOnChange: true. Los cambios realizados en los archivos appsettings.json y appsettings.{Environment}.jsondespués de que la aplicación se inicie los lee el proveedor de configuración JSON.

Enlace de datos de configuración jerárquica mediante el patrón de opciones

La mejor manera de leer valores de configuración relacionados es usar el patrón de opciones. Por ejemplo, para leer los siguientes valores de configuración:

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

Cree la siguiente clase PositionOptions:

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

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

Una clase de opciones:

  • Debe ser no abstracta con un constructor público sin parámetros.
  • Todas las propiedades de lectura y escritura públicas del tipo están enlazadas.
  • Los campos no se enlazan. En el código anterior, Position no está enlazado. El campo Position se usa para que la cadena "Position" no se tenga que codificar de forma rígida en la aplicación al enlazar la clase a un proveedor de configuración.

El código siguiente:

  • Llama a ConfigurationBinder.Bind para enlazar la clase PositionOptions a la sección Position.
  • Muestra los datos de configuración de 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}");
    }
}

En el código anterior, de forma predeterminada, los cambios en el archivo de configuración de JSON producidos una vez iniciada la aplicación se leen.

ConfigurationBinder.Get<T> enlaza y devuelve el tipo especificado. Puede ser más conveniente usar ConfigurationBinder.Get<T> que ConfigurationBinder.Bind. En el código siguiente se muestra cómo puede usar ConfigurationBinder.Get<T> con la clase 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}");
    }
}

En el código anterior, de forma predeterminada, los cambios en el archivo de configuración de JSON producidos una vez iniciada la aplicación se leen.

Un enfoque alternativo a la hora de usar el patrón de opciones consiste en enlazar la sección Position y agregarla al contenedor del servicio de inserción de dependencias. En el siguiente código se agrega PositionOptions al contenedor de servicios con Configure y se enlaza a la configuración:

using ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

A partir del código anterior, el siguiente código lee las opciones de posición:

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

En el código anterior, los cambios en el archivo de configuración JSON producidos una vez iniciada la aplicación no se leen. Para leer los cambios una vez iniciada la aplicación, use IOptionsSnapshot.

Si usa la configuración predeterminada, los archivosappsettings.json y appsettings.{Environment}.json están habilitados con reloadOnChange: true. Los cambios realizados en los archivos appsettings.json y appsettings.{Environment}.jsondespués de que la aplicación se inicie los lee el proveedor de configuración JSON.

Consulte la sección Proveedor de configuración JSJSON de este documento para obtener información sobre cómo agregar más archivos de configuración JSON.

Combinación de colecciones de servicios

Tenga en cuenta el siguiente método que registra los servicios y configura las opciones:

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

Los grupos de registros relacionados pueden moverse a un método de extensión para registrar los servicios. Por ejemplo, los servicios de configuración se agregan a la siguiente clase:

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

Los servicios restantes se registran en una clase similar. El siguiente código usa los nuevos métodos de extensión para registrar los servicios:

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: Cada método de extensión services.Add{GROUP_NAME} agrega servicios y potencialmente los configura. Por ejemplo, AddControllersWithViews agrega los controladores MVC de servicios con las vistas que se requieren y AddRazorPages agrega los servicios que Razor Pages requiere.

Seguridad y secretos de usuario

Directrices para los datos de configuración:

  • Nunca almacene contraseñas u otros datos confidenciales en el código del proveedor de configuración o en archivos de configuración de texto sin formato. Se puede usar la herramienta Administrador de secretos para almacenar secretos en desarrollo.
  • No use secretos de producción en los entornos de desarrollo o pruebas.
  • Especifique los secretos fuera del proyecto para que no se confirmen en un repositorio de código fuente de manera accidental.

De forma predeterminada, el origen de configuración de los secretos de usuario se registra después de los orígenes de configuración JSON. Por lo tanto, las claves de secretos de usuario tienen prioridad sobre las claves de appsettings.json y appsettings.{Environment}.json.

Para obtener más información sobre cómo almacenar contraseñas u otros datos confidenciales consulte:

Azure Key Vault almacena de forma segura secretos de aplicación para aplicaciones de ASP.NET Core. Para obtener más información, vea Proveedor de configuración de Azure Key Vault en ASP.NET Core.

Variables de entorno sin prefijo

Las variables de entorno sin prefijo son variables de entorno distintas de las que exhiben los prefijos ASPNETCORE_ o DOTNET_. Por ejemplo, las plantillas de aplicación web de ASP.NET Core establecen "ASPNETCORE_ENVIRONMENT": "Development" en launchSettings.json. Para obtener más información sobre las variables de entorno ASPNETCORE_ y DOTNET_, consulte:

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 los secretos de usuario. 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 los secretos de usuario.

El separador : no funciona con claves jerárquicas de variables de entorno en todas las plataformas. __, el carácter de subrayado doble, tiene las siguientes características:

  • Es compatible con todas las plataformas. Por ejemplo, el separador : no es compatible con Bash, pero __ sí.
  • Se reemplaza automáticamente por un signo :.

Los siguientes comandos set:

  • Establecen las claves de entorno y los valores del ejemplo anterior en Windows.
  • Prueban la configuración al usar la descarga de ejemplo. El comando dotnet run debe ejecutarse en el directorio del proyecto.
set MyKey="My key from Environment"
set Position__Title=Environment_Editor
set Position__Name=Environment_Rick
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 los exploradores que se inician con Visual Studio.

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

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:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

En el código anterior:

  • builder.Configuration.AddEnvironmentVariables(prefix: "MyCustomPrefix_") 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 la sección Proveedor de configuración JSON.
  • Las variables de entorno establecidas con el prefijo MyCustomPrefix_ 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 MyCustomPrefix_MyKey="My key with MyCustomPrefix_ Environment"
set MyCustomPrefix_Position__Title=Editor_with_customPrefix
set MyCustomPrefix_Position__Name=Environment_Rick_cp
dotnet run

La configuración predeterminada carga las variables de entorno y los argumentos de la línea de comandos con los prefijos DOTNET_ y ASPNETCORE_. ASP.NET Core usa los prefijos DOTNET_ y ASPNETCORE_ para la configuración del host y 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.

Para más información, consulte Aplicaciones de Azure: Invalidación de la configuración de la aplicación mediante Azure Portal.

Consulte la sección Prefijos de cadena de conexión para obtener información sobre las cadenas de conexión de base de datos de Azure.

Nomenclatura de variables de entorno

Los nombres de las variables de entorno reflejan la estructura de un archivo appsettings.json . Cada elemento de la jerarquía está separado por un carácter de subrayado doble (preferible) o un signo de dos puntos. Cuando la estructura del elemento incluye una matriz, el índice de la matriz se debe tratar como un nombre de elemento adicional en esta ruta de acceso. Considere el siguiente archivo appsettings.json y sus valores equivalentes representados como variables de entorno.

appsettings.json

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

variables de entorno

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

Variables de entorno configuradas en el archivo launchSettings.json generado

Las variables de entorno configuradas en launchSettings.json invalidan aquellas configuradas en el entorno del sistema. Por ejemplo, las plantillas web ASP.NET Core generan un archivo launchSettings.json que establece la configuración del punto de conexión en:

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

Al configurar applicationUrl, se establece la variable de entorno ASPNETCORE_URLS y se invalidan los valores establecidos en el entorno.

Variables de entorno de escape en Linux

En Linux, el valor de las variables de entorno de URL debe ser de escape, para que systemd pueda analizarlas. Uso de la herramienta de Linux systemd-escape que produce http:--localhost:5001

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

Visualización de las variables de entorno

En el código siguiente se muestran las variables de entorno y los valores en el inicio de la aplicación, lo que puede resultar útil al depurar la configuración del entorno:

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

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

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 aplicaciones en el entorno de desarrollo.
  • 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.

Argumentos de la línea de comandos

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

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

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

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

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

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

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

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.

Asignaciones de modificador

Las asignaciones de modificador admiten la lógica de sustitución de nombres de clave. Proporcione un diccionario de reemplazos de modificador al método AddCommandLine.

Cuando se usa el diccionario de asignaciones de modificador, se comprueba en el diccionario si una clave coincide con la clave proporcionada por un argumento de línea de comandos. Si la clave de la línea de comandos se encuentra en el diccionario, se devuelve el valor del diccionario para establecer el par clave-valor en la configuración de la aplicación. Se requiere una asignación de conmutador para cualquier clave de línea de comandos precedida por un solo guion (-).

Reglas de clave del diccionario de asignaciones de modificador:

  • Los modificadores deben comenzar con - o --.
  • El diccionario de asignaciones de modificador no debe contener claves duplicadas.

Para usar un diccionario de asignaciones de modificador, páselo a la llamada 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();

La ejecución del siguiente comando sirve para probar el reemplazo de claves:

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

El código siguiente muestra los valores de clave para las claves reemplazadas:

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

En el caso de las aplicaciones que usen las asignaciones de modificador, la llamada a CreateDefaultBuilder no tiene que pasar argumentos. En la llamada de AddCommandLine al método CreateDefaultBuilder, no se incluyen modificadores asignados y no hay forma de pasar el diccionario de asignación de modificador a CreateDefaultBuilder. La solución no es pasar los argumentos de CreateDefaultBuilder, sino permitir que el método AddCommandLine del método ConfigurationBuilder procese tanto los argumentos como el diccionario de asignación de modificador.

Configuración del entorno y de los argumentos de la línea de comandos con Visual Studio

Los argumentos de entorno y de línea de comandos se pueden establecer en Visual Studio desde el cuadro de diálogo de perfiles de inicio:

  • En el Explorador de soluciones, haga clic con el botón derecho en el proyecto y seleccione Propiedades.
  • Seleccione la pestaña Depurar > General y luego Abrir la interfaz de usuario de perfiles de inicio de depuración.

Datos de configuración jerárquica

La API de configuración lee los datos de configuración jerárquica al disminuir los datos jerárquicos mediante el uso de un delimitador en las claves de configuración.

La descarga de ejemplo contiene el siguiente archivo appsettings.json:

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

El siguiente código de la descarga de ejemplo muestra algunas de las opciones de configuración:

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 mejor manera de leer datos de configuración jerárquica es usar el patrón de opciones. Para obtener más información, vea la sección Enlace de datos de configuración jerárquica en este documento.

Los métodos GetSection y GetChildren están disponibles para aislar las secciones y los elementos secundarios de una sección en los datos de configuración. Estos métodos se describen más adelante en la sección GetSection, GetChildren y Exists.

Claves y valores de configuración

Las claves de configuración:

  • No distinguen mayúsculas de minúsculas. Por ejemplo, ConnectionString y connectionstring se consideran claves equivalente.
  • Si se establece una clave y un valor en más de un proveedor de configuración, se usa el valor del último proveedor agregado. Para obtener más información, vea la sección Configuración predeterminada.
  • Claves jerárquicas
    • Dentro de la API de configuración, un separador de dos puntos (:) funciona en todas las plataformas.
    • En las variables de entorno, puede que un separador de dos puntos no funcione en todas las plataformas. Todas las plataformas admiten un carácter de subrayado doble, __, que se convierte automáticamente en un signo de dos puntos :.
    • En Azure Key Vault, las claves jerárquicas usan -- como separador. El proveedor de configuración de Azure Key Vault reemplaza automáticamente -- con : cuando los secretos se cargan en la configuración de la aplicación.
  • ConfigurationBinder admite enlazar matrices a objetos con los índices de matriz en las claves de configuración. El enlace de matriz se describe en la sección Enlace de una matriz a una clase.

Los valores de configuración:

  • Son cadenas.
  • Los valores NULL no se pueden almacenar en la configuración ni enlazar a los objetos.

Proveedores de configuración

La siguiente tabla muestra los proveedores de configuración disponibles para las aplicaciones de ASP.NET Core.

Proveedor Proporciona la configuración de
Proveedor de configuración de Azure Key Vault Azure Key Vault
Proveedor de configuración de aplicaciones de Azure Configuración de aplicaciones de Azure
Proveedor de configuración de línea de comandos Parámetros de la línea de comandos
Proveedor de configuración personalizada Origen personalizado
Proveedor de configuración de variables de entorno Variables de entorno
Proveedor de configuración de archivo Archivos INI, JSON y XML
Proveedor de configuración de clave por archivo Archivos de directorio
Proveedor de configuración de memoria Colecciones en memoria
Secretos de usuario Archivo en el directorio del perfil de usuario

Los orígenes de configuración se leen en el orden en que se especifican sus proveedores de configuración. Ordene los proveedores de configuración en el código para cumplir con las prioridades relacionadas con los orígenes de configuración subyacentes que la aplicación necesita.

Esta es una secuencia típica de proveedores de configuración:

  1. appsettings.json
  2. appsettings.{Environment}.json
  3. Secretos de usuario
  4. Variables de entorno con el proveedor de configuración de variables de entorno.
  5. Argumentos de la línea de comandos con el proveedor de configuración de línea de comandos.

Una práctica común es agregar el proveedor de configuración de línea de comandos al final en una serie de proveedores para permitir que los argumentos de la línea de comandos reemplacen la configuración establecida por el resto de los proveedores.

La secuencia de proveedores anterior se usa en la configuración predeterminada.

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

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 INI

IniConfigurationProvider carga la configuración desde pares clave-valor de archivo INI en tiempo de ejecución.

El código siguiente borra todos los proveedores de configuración y agrega varios:

var builder = WebApplication.CreateBuilder(args);

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

    var env = hostingContext.HostingEnvironment;

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

    config.AddEnvironmentVariables();

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

builder.Services.AddRazorPages();

var app = builder.Build();

En el código anterior, la configuración de los archivos MyIniConfig.ini y MyIniConfig.{Environment}.ini se reemplaza por la configuración de:

La descarga de ejemplo contiene el siguiente archivo MyIniConfig.ini:

MyKey="MyIniConfig.ini Value"

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

[Logging:LogLevel]
Default=Information
Microsoft=Warning

El siguiente código de la descarga de ejemplo muestra algunas de las configuraciones anteriores:

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

Proveedor de configuraciónJSON

JsonConfigurationProvider carga la configuración desde pares clave-valor de archivos 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.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

El código anterior:

Por lo general, no conviene que un archivo JSON personalizado invalide los valores establecidos en el proveedor de configuración de variables de entorno ni en el proveedor de configuración de línea de comandos.

Proveedor de configuración XML

XmlConfigurationProvider carga la configuración desde pares clave-valor de archivo XML en tiempo de ejecución.

El código siguiente borra todos los proveedores de configuración y agrega varios:

var builder = WebApplication.CreateBuilder(args);

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

    var env = hostingContext.HostingEnvironment;

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

    config.AddEnvironmentVariables();

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

builder.Services.AddRazorPages();

var app = builder.Build();

En el código anterior, la configuración de los archivos MyXMLFile.xml y MyXMLFile.{Environment}.xml se reemplaza por la configuración de:

La descarga de ejemplo contiene el siguiente archivo MyXMLFile.xml:

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

El siguiente código de la descarga de ejemplo muestra algunas de las configuraciones anteriores:

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

Los elementos de repetición que usan el mismo nombre de elemento funcionan si el atributo name se usa para distinguir los elementos:

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

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

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 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 contiene 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((hostingContext, config) =>
{
    var path = Path.Combine(
        Directory.GetCurrentDirectory(), "path/to/files");
    config.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:

var builder = WebApplication.CreateBuilder(args);

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

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

    config.AddInMemoryCollection(Dict);

    config.AddEnvironmentVariables();

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

builder.Services.AddRazorPages();

var app = builder.Build();

El siguiente código de la descarga de ejemplo muestra las opciones de configuración anteriores:

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

En el código anterior, config.AddInMemoryCollection(Dict) 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 la sección Proveedor de configuración JSON.

Consulte la sección Enlace de matrices para ver otro ejemplo que usa MemoryConfigurationProvider.

Configuración del punto de conexión de Kestrel

La configuración del punto de conexión específico de Kestrel invalida todas las configuraciones del punto de conexión entre servidores. Las configuraciones del punto de conexión entre servidores incluyen:

Tenga en cuenta el archivo siguiente appsettings.json usado en una aplicación web de ASP.NET Core:

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

Cuando el marcado resaltado anterior se usa en una aplicación web de ASP.NET Core y la aplicación se inicia en la línea de comandos con la siguiente configuración del punto de conexión entre servidores:

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

Kestrel se enlaza con el punto de conexión configurado específicamente para Kestrel en el archivo appsettings.json (https://localhost:9999) y no https://localhost:7777.

Considere el punto de conexión específico de Kestrel configurado como una variable de entorno:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

En la variable de entorno anterior, Https es el nombre del punto de conexión específico de Kestrel. En el archivo appsettings.json anterior también se define un punto de conexión específico de Kestrel denominado Https. De manera predeterminada, las variables de entorno que utilizan el proveedor de configuración de variables de entorno se leen después de appsettings.{Environment}.json, por lo tanto, la variable de entorno anterior se usa para el punto de conexión Https.

GetValue

ConfigurationBinder.GetValue extrae un único valor de la configuración con una clave determinada y lo convierte al tipo especificado:

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

En el código anterior, si NumberKey no se encuentra en la configuración, se usa el valor predeterminado de 99.

GetSection, GetChildren y Exists

Para los ejemplos siguientes, considere el siguiente archivo MySubsection.json:

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

El código siguiente agrega MySubsection.json a los proveedores de configuración:

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

GetSection

IConfiguration.GetSection devuelve una subsección de la configuración con la clave de subsección especificada.

El código siguiente devuelve los valores de 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"]}'");
    }
}

El código siguiente devuelve los valores de 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 nunca devuelve null. Si no se encuentra una sección que coincida, se devuelve una IConfigurationSection vacía.

Cuando GetSection devuelve una sección coincidente, Value no se rellena. Se devuelven Key y Path si la sección existe.

GetChildren y Exists

El código siguiente llama a IConfiguration.GetChildren y devuelve los valores de 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);
    }
}

El código anterior llama a ConfigurationExtensions.Exists para comprobar que la sección existe:

Enlace de matrices

ConfigurationBinder.Bind admite enlazar matrices a objetos con los índices de matriz en las claves de configuración. Cualquier formato de matriz que exponga un segmento de clave numérica es capaz de enlazar una matriz a una matriz de clase POCO.

Tenga en cuenta este archivo MyArray.json de la descarga de ejemplo:

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

El código siguiente agrega MyArray.json a los proveedores de configuración:

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

El código siguiente lee la configuración y muestra los valores:

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

El código anterior devuelve el siguiente resultado:

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

En el resultado anterior, el índice 3 tiene el valor value40, que corresponde a "4": "value40", en MyArray.json. Los índices de matriz enlazados son continuos y no están enlazados al índice de la clave de configuración. El enlazador de configuración no es capaz de enlazar los valores NULL ni de crear entradas NULL en objetos enlazados.

Proveedores de configuración personalizada

La aplicación de ejemplo muestra cómo crear un proveedor de configuración básica que lee los pares clave-valor de configuración desde una base de datos mediante Entity Framework (EF).

El proveedor tiene las siguientes características:

  • La base de datos en memoria de EF se usa para fines de demostración. Para usar una base de datos que requiere una cadena de conexión, implemente un ConfigurationBuilder secundario para suministrar la cadena de conexión desde otro proveedor de configuración.
  • El proveedor lee una tabla de base de datos en la configuración en el inicio. El proveedor no consulta la base de datos por clave.
  • La función de recarga en cambio no se implementa, por lo que actualizar la base de datos después del inicio de la aplicación no afecta a la configuración de la aplicación.

Defina una entidad EFConfigurationValue para almacenar los valores de configuración en la base de datos.

Models/EFConfigurationValue.cs:

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

Agregue un EFConfigurationContext para almacenar y tener acceso a los valores configurados.

EFConfigurationProvider/EFConfigurationContext.cs:

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

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

Cree una clase que implemente 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);
}

Cree el proveedor de configuración personalizado heredando de ConfigurationProvider. El proveedor de configuración inicializa la base de datos cuando está vacía. Puesto que las claves de configuración no distinguen entre mayúsculas y minúsculas, el diccionario empleado para iniciar la base de datos se crea con el comparador que tampoco hace tal distinción (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 método de extensión AddEFConfiguration permite agregar el origen de configuración 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));
    }
}

En el código siguiente se muestra cómo puede usar el EFConfigurationProvider personalizado en Program.cs:

//using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

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

var app = builder.Build();

app.Run();

Configuración de acceso con inserción de dependencias (DI)

La configuración se puede insertar en los servicios mediante la inserción de dependencias (DI) resolviendo el servicio IConfiguration:

public class Service
{
    private readonly IConfiguration _config;

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

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

        // ...
    }
}

Para obtener información sobre cómo acceder a valores mediante IConfiguration, vea GetValue y GetSection, GetChildren y Exists en este artículo.

Acceso a la configuración en Razor Pages

En el código siguiente se muestran los datos de configuración en una página de RazorPages:

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

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

En el siguiente código se agrega MyOptions al contenedor de servicios con Configure y se enlaza a la configuración:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

En el marcado siguiente se usa la directiva @injectRazor para resolver y mostrar los valores de las opciones:

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

Acceso a la configuración en un archivo de vista de MVC

En el código siguiente se muestran los datos de configuración de una vista de MVC:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

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

Acceder a la configuración en Program.cs

El código siguiente accede a la configuración en el archivo Program.cs.

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

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

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

app.Logger.LogInformation($"KeyOne = {key1}");
app.Logger.LogInformation($"KeyTwo = {key2}");

app.Run();

Configurar opciones con un delegado

Las opciones configuradas en un delegado invalidan los valores establecidos en los proveedores de configuración.

En el código siguiente, se agrega un servicio IConfigureOptions<TOptions> al contenedor de servicios. Usa un delegado para configurar los valores de 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();

En el código siguiente se muestran los valores de las opciones:

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

En el ejemplo anterior, los valores de Option1 y Option2 se especifican en appsettings.json y, luego, se reemplazan por el delegado configurado.

Configuración de host y de aplicación

Antes de configurar e iniciar la aplicación, se configura e inicia un host. El host es responsable de la administración del inicio y la duración de la aplicación. Tanto la aplicación como el host se configuran mediante los proveedores de configuración que se describen en este tema. Los pares clave-valor de configuración del host también se incluyen en la configuración de la aplicación. Para obtener más información sobre cómo se usan los proveedores de configuración cuando se compila el host y cómo afectan los orígenes de configuración a la configuración del host, consulte la información general sobre conceptos básicos de ASP.NET Core.

Configuración predeterminada del host

Para obtener más información sobre la configuración predeterminada al usar el host de web, vea la versión de este tema para ASP.NET Core 2.2.

  • La configuración del host la proporcionan los siguientes elementos:
  • La configuración predeterminada del host de web se ha establecido (ConfigureWebHostDefaults):
    • Kestrel se usa como el servidor web y se ha configurado mediante los proveedores de configuración de la aplicación.
    • Agregar el middleware de filtrado de host
    • Agregue el middleware de encabezados reenviados si la variable de entorno ASPNETCORE_FORWARDEDHEADERS_ENABLED se establece en true.
    • Habilite la integración con IIS.

Otra configuración

Este tema solo concierne a la configuración de aplicaciones. Otros aspectos de la ejecución y el hospedaje de aplicaciones ASP.NET Core se configuran mediante archivos de configuración que no se describen en este tema:

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

Para más información sobre cómo migrar la configuración de aplicaciones de versiones anteriores de ASP.NET, consulte Migrar de ASP.NET a ASP.NET Core.

Agregar configuración a partir de un ensamblado externo

Una implementación de IHostingStartup permite agregar mejoras a una aplicación al iniciarla a partir de un ensamblado externo fuera de la clase Startup de esta. Para obtener más información, consulte Uso de ensamblados de inicio de hospedaje en ASP.NET Core.

Recursos adicionales

La configuración de ASP.NET Core se realiza mediante uno o varios proveedores de configuración. Los proveedores de configuración leen los datos sobre los ajustes de los pares clave-valor mediante distintos orígenes de configuración:

  • Archivos de configuración, como appsettings.json
  • Variables de entorno
  • Azure Key Vault
  • Configuración de aplicaciones de Azure
  • Argumentos de la línea de comandos
  • Proveedores personalizados (instalados o creados)
  • Archivos de directorio
  • Objetos de .NET en memoria

En este tema se proporciona información sobre la configuración de ASP.NET Core. Para más información sobre el uso de la configuración en las aplicaciones de consola, consulte Configuración de .NET.

Vea o descargue el código de ejemplo (cómo descargarlo)

Configuración predeterminada

Las aplicaciones web de ASP.NET Core creadas con dotnet new o con Visual Studio generan el código siguiente:

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

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

CreateDefaultBuilder proporciona la configuración predeterminada para la aplicación en el orden siguiente:

  1. ChainedConfigurationProvider: agrega un elemento IConfiguration existente como origen. En el caso de una configuración predeterminada, agrega la configuración del host y lo establece como el primer origen para la configuración de la aplicación.
  2. appsettings.json que usa el proveedor de configuración JSON
  3. appsettings.{Environment}.json que usa el proveedor de configuración JSON Por ejemplo, appsettings.Production.json y appsettings.Development.json.
  4. Secretos de la aplicación cuando la aplicación se ejecuta en el entorno Development.
  5. Variables de entorno con el proveedor de configuración de variables de entorno.
  6. Argumentos de la línea de comandos con el proveedor de configuración de línea de comandos.

Los proveedores de configuración que se agregan posteriormente invalidan los ajustes de configuración de la clave anteriores. Por ejemplo, si MyKey se establece tanto en appsettings.json como en el entorno, se usará el valor del entorno. Con los proveedores de configuración predeterminados, el proveedor de configuración de línea de comandos reemplaza al resto de proveedores.

Para obtener más información sobre CreateDefaultBuilder, consulte el artículo Configuración predeterminada del generador.

El código siguiente muestra los proveedores de configuración habilitados en el orden en el que se han agregado:

public class Index2Model : PageModel
{
    private IConfigurationRoot ConfigRoot;

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

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

        return Content(str);
    }
}

appsettings.json

Fíjese en el siguiente archivo appsettings.json :

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

El siguiente código de la descarga de ejemplo muestra algunas de las configuraciones anteriores:

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

El elemento JsonConfigurationProvider predeterminado carga la configuración en el siguiente orden:

  1. appsettings.json
  2. appsettings.{Environment}.json: por ejemplo, los archivos appsettings.Production.json y appsettings.Development.json. La versión del entorno del archivo se carga en función de IHostingEnvironment.EnvironmentName. Para obtener más información, consulte Usar varios entornos en ASP.NET Core.

Los valores de appsettings.{Environment}.json invalidan las claves en appsettings.json. Por ejemplo, de forma predeterminada:

  • En la fase de desarrollo, la configuración appsettings.Development.json sobrescribe los valores encontrados en appsettings.json.
  • En la fase de producción, la configuración appsettings.Production.json sobrescribe los valores encontrados en appsettings.json. Por ejemplo, al implementar la aplicación en Azure.

Si se debe garantizar un valor de configuración, consulte GetValue. En el ejemplo anterior solo se leen cadenas y no se admite un valor predeterminado.

Si usa la configuración predeterminada, los archivosappsettings.json y appsettings.{Environment}.json están habilitados con reloadOnChange: true. Los cambios realizados en los archivos appsettings.json y appsettings.{Environment}.jsondespués de que la aplicación se inicie los lee el proveedor de configuración JSON.

Enlace de datos de configuración jerárquica mediante el patrón de opciones

La mejor manera de leer valores de configuración relacionados es usar el patrón de opciones. Por ejemplo, para leer los siguientes valores de configuración:

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

Cree la siguiente clase PositionOptions:

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

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

Una clase de opciones:

  • Debe ser no abstracta con un constructor público sin parámetros.
  • Todas las propiedades de lectura y escritura públicas del tipo están enlazadas.
  • Los campos no se enlazan. En el código anterior, Position no está enlazado. La propiedad Position se usa para que la cadena "Position" no tenga que estar codificada de forma rígida en la aplicación al enlazar la clase a un proveedor de configuración.

El código siguiente:

  • Llama a ConfigurationBinder.Bind para enlazar la clase PositionOptions a la sección Position.
  • Muestra los datos de configuración de 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}");
    }
}

En el código anterior, de forma predeterminada, los cambios en el archivo de configuración de JSON producidos una vez iniciada la aplicación se leen.

ConfigurationBinder.Get<T> enlaza y devuelve el tipo especificado. Puede ser más conveniente usar ConfigurationBinder.Get<T> que ConfigurationBinder.Bind. En el código siguiente se muestra cómo puede usar ConfigurationBinder.Get<T> con la clase 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}");
    }
}

En el código anterior, de forma predeterminada, los cambios en el archivo de configuración de JSON producidos una vez iniciada la aplicación se leen.

Un enfoque alternativo a la hora de usar el patrón de opciones consiste en enlazar la sección Position y agregarla al contenedor del servicio de inserción de dependencias. En el siguiente código se agrega PositionOptions al contenedor de servicios con Configure y se enlaza a la configuración:

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

A partir del código anterior, el siguiente código lee las opciones de posición:

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

En el código anterior, los cambios en el archivo de configuración JSON producidos una vez iniciada la aplicación no se leen. Para leer los cambios una vez iniciada la aplicación, use IOptionsSnapshot.

Si usa la configuración predeterminada, los archivosappsettings.json y appsettings.{Environment}.json están habilitados con reloadOnChange: true. Los cambios realizados en los archivos appsettings.json y appsettings.{Environment}.jsondespués de que la aplicación se inicie los lee el proveedor de configuración JSON.

Consulte la sección Proveedor de configuración JSJSON de este documento para obtener información sobre cómo agregar más archivos de configuración JSON.

Combinación de colecciones de servicios

Tenga en cuenta el siguiente método ConfigureServices, que registra los servicios y configura las opciones:

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

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

    services.AddRazorPages();
}

Los grupos de registros relacionados pueden moverse a un método de extensión para registrar los servicios. Por ejemplo, los servicios de configuración se agregan a la siguiente clase:

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

Los servicios restantes se registran en una clase similar. El siguiente método ConfigureServices usa los nuevos métodos de extensión para registrar los servicios:

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

    services.AddRazorPages();
}

Nota: Cada método de extensión services.Add{GROUP_NAME} agrega servicios y potencialmente los configura. Por ejemplo, AddControllersWithViews agrega los controladores MVC de servicios con las vistas que se requieren y AddRazorPages agrega los servicios que Razor Pages requiere. Se recomienda que las aplicaciones sigan la convención de nomenclatura de crear métodos de extensión en el espacio de nombres Microsoft.Extensions.DependencyInjection. Creación de métodos de extensión en el espacio de nombres Microsoft.Extensions.DependencyInjection:

  • Encapsula grupos de registros de servicio.
  • Proporciona acceso práctico de IntelliSense al servicio.

Seguridad y secretos de usuario

Directrices para los datos de configuración:

  • Nunca almacene contraseñas u otros datos confidenciales en el código del proveedor de configuración o en archivos de configuración de texto sin formato. Se puede usar la herramienta Administrador de secretos para almacenar secretos en desarrollo.
  • No use secretos de producción en los entornos de desarrollo o pruebas.
  • Especifique los secretos fuera del proyecto para que no se confirmen en un repositorio de código fuente de manera accidental.

De forma predeterminada, el origen de configuración de los secretos de usuario se registra después de los orígenes de configuración JSON. Por lo tanto, las claves de secretos de usuario tienen prioridad sobre las claves de appsettings.json y appsettings.{Environment}.json.

Para obtener más información sobre cómo almacenar contraseñas u otros datos confidenciales consulte:

Azure Key Vault almacena de forma segura secretos de aplicación para aplicaciones de ASP.NET Core. Para obtener más información, vea Proveedor de configuración de Azure Key Vault en ASP.NET Core.

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 los secretos de usuario. 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 los secretos de usuario.

El separador : no funciona con claves jerárquicas de variables de entorno en todas las plataformas. __, el carácter de subrayado doble, tiene las siguientes características:

  • Es compatible con todas las plataformas. Por ejemplo, el separador : no es compatible con Bash, pero __ sí.
  • Se reemplaza automáticamente por un signo :.

Los siguientes comandos set:

  • Establecen las claves de entorno y los valores del ejemplo anterior en Windows.
  • Prueban la configuración al usar la descarga de ejemplo. El comando dotnet run debe ejecutarse en el directorio del proyecto.
set MyKey="My key from Environment"
set Position__Title=Environment_Editor
set Position__Name=Environment_Rick
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 los exploradores que se inician con Visual Studio.

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

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:

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

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

En el código anterior:

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

Los siguientes comandos prueban el prefijo personalizado:

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 configuración predeterminada carga las variables de entorno y los argumentos de la línea de comandos con los prefijos DOTNET_ y ASPNETCORE_. ASP.NET Core usa los prefijos DOTNET_ y ASPNETCORE_ para la configuración del host y 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.

Para más información, consulte Aplicaciones de Azure: Invalidación de la configuración de la aplicación mediante Azure Portal.

Consulte la sección Prefijos de cadena de conexión para obtener información sobre las cadenas de conexión de base de datos de Azure.

Nomenclatura de variables de entorno

Los nombres de las variables de entorno reflejan la estructura de un archivo appsettings.json . Cada elemento de la jerarquía está separado por un carácter de subrayado doble (preferible) o un signo de dos puntos. Cuando la estructura del elemento incluye una matriz, el índice de la matriz se debe tratar como un nombre de elemento adicional en esta ruta de acceso. Considere el siguiente archivo appsettings.json y sus valores equivalentes representados como variables de entorno.

appsettings.json

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

variables de entorno

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

Variables de entorno configuradas en el archivo launchSettings.json generado

Las variables de entorno configuradas en launchSettings.json invalidan aquellas configuradas en el entorno del sistema. Por ejemplo, las plantillas web ASP.NET Core generan un archivo launchSettings.json que establece la configuración del punto de conexión en:

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

Al configurar applicationUrl, se establece la variable de entorno ASPNETCORE_URLS y se invalidan los valores establecidos en el entorno.

Variables de entorno de escape en Linux

En Linux, el valor de las variables de entorno de URL debe ser de escape, para que systemd pueda analizarlas. Uso de la herramienta de Linux systemd-escape que produce http:--localhost:5001

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

Visualización de las variables de entorno

En el código siguiente se muestran las variables de entorno y los valores en el inicio de la aplicación, lo que puede resultar útil al depurar la configuración del entorno:

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

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

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

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 aplicaciones en el entorno de desarrollo.
  • 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.

Argumentos de la línea de comandos

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

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

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

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

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

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

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

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.

Asignaciones de modificador

Las asignaciones de modificador admiten la lógica de sustitución de nombres de clave. Proporcione un diccionario de reemplazos de modificador al método AddCommandLine.

Cuando se usa el diccionario de asignaciones de modificador, se comprueba en el diccionario si una clave coincide con la clave proporcionada por un argumento de línea de comandos. Si la clave de la línea de comandos se encuentra en el diccionario, se devuelve el valor del diccionario para establecer el par clave-valor en la configuración de la aplicación. Se requiere una asignación de conmutador para cualquier clave de línea de comandos precedida por un solo guion (-).

Reglas de clave del diccionario de asignaciones de modificador:

  • Los modificadores deben comenzar con - o --.
  • El diccionario de asignaciones de modificador no debe contener claves duplicadas.

Para usar un diccionario de asignaciones de modificador, páselo a la llamada a AddCommandLine:

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

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

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

El código siguiente muestra los valores de clave para las claves reemplazadas:

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

El siguiente comando sirve para probar el reemplazo de claves:

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

En el caso de las aplicaciones que usen las asignaciones de modificador, la llamada a CreateDefaultBuilder no tiene que pasar argumentos. En la llamada de AddCommandLine al método CreateDefaultBuilder, no se incluyen modificadores asignados y no hay forma de pasar el diccionario de asignación de modificador a CreateDefaultBuilder. La solución no es pasar los argumentos de CreateDefaultBuilder, sino permitir que el método AddCommandLine del método ConfigurationBuilder procese tanto los argumentos como el diccionario de asignación de modificador.

Configuración del entorno y de los argumentos de la línea de comandos con Visual Studio

En la imagen siguiente se muestra cómo configurar el entorno y los argumentos de la línea de comandos con Visual Studio:

Pestaña Depurar de VS

En la versión preliminar 4 y posteriores de la versión 16.10 de Visual Studio 2019, la configuración del entorno y de los argumentos de la línea de comandos se realiza en la interfaz de usuario de los perfiles de inicio:

Interfaz de usuario de los perfiles de inicio

Datos de configuración jerárquica

La API de configuración lee los datos de configuración jerárquica al disminuir los datos jerárquicos mediante el uso de un delimitador en las claves de configuración.

La descarga de ejemplo contiene el siguiente archivo appsettings.json:

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

El siguiente código de la descarga de ejemplo muestra algunas de las opciones de configuración:

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 mejor manera de leer datos de configuración jerárquica es usar el patrón de opciones. Para obtener más información, vea la sección Enlace de datos de configuración jerárquica en este documento.

Los métodos GetSection y GetChildren están disponibles para aislar las secciones y los elementos secundarios de una sección en los datos de configuración. Estos métodos se describen más adelante en la sección GetSection, GetChildren y Exists.

Claves y valores de configuración

Las claves de configuración:

  • No distinguen mayúsculas de minúsculas. Por ejemplo, ConnectionString y connectionstring se consideran claves equivalente.
  • Si se establece una clave y un valor en más de un proveedor de configuración, se usa el valor del último proveedor agregado. Para obtener más información, vea la sección Configuración predeterminada.
  • Claves jerárquicas
    • Dentro de la API de configuración, un separador de dos puntos (:) funciona en todas las plataformas.
    • En las variables de entorno, puede que un separador de dos puntos no funcione en todas las plataformas. Todas las plataformas admiten un carácter de subrayado doble, __, que se convierte automáticamente en un signo de dos puntos :.
    • En Azure Key Vault, las claves jerárquicas usan -- como separador. El proveedor de configuración de Azure Key Vault reemplaza automáticamente -- con : cuando los secretos se cargan en la configuración de la aplicación.
  • ConfigurationBinder admite enlazar matrices a objetos con los índices de matriz en las claves de configuración. El enlace de matriz se describe en la sección Enlace de una matriz a una clase.

Los valores de configuración:

  • Son cadenas.
  • Los valores NULL no se pueden almacenar en la configuración ni enlazar a los objetos.

Proveedores de configuración

La siguiente tabla muestra los proveedores de configuración disponibles para las aplicaciones de ASP.NET Core.

Proveedor Proporciona la configuración de
Proveedor de configuración de Azure Key Vault Azure Key Vault
Proveedor de configuración de aplicaciones de Azure Configuración de aplicaciones de Azure
Proveedor de configuración de línea de comandos Parámetros de la línea de comandos
Proveedor de configuración personalizada Origen personalizado
Proveedor de configuración de variables de entorno Variables de entorno
Proveedor de configuración de archivo Archivos INI, JSON y XML
Proveedor de configuración de clave por archivo Archivos de directorio
Proveedor de configuración de memoria Colecciones en memoria
Secretos de usuario Archivo en el directorio del perfil de usuario

Los orígenes de configuración se leen en el orden en que se especifican sus proveedores de configuración. Ordene los proveedores de configuración en el código para cumplir con las prioridades relacionadas con los orígenes de configuración subyacentes que la aplicación necesita.

Esta es una secuencia típica de proveedores de configuración:

  1. appsettings.json
  2. appsettings.{Environment}.json
  3. Secretos de usuario
  4. Variables de entorno con el proveedor de configuración de variables de entorno.
  5. Argumentos de la línea de comandos con el proveedor de configuración de línea de comandos.

Una práctica común es agregar el proveedor de configuración de línea de comandos al final en una serie de proveedores para permitir que los argumentos de la línea de comandos reemplacen la configuración establecida por el resto de los proveedores.

La secuencia de proveedores anterior se usa en la configuración predeterminada.

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

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 INI

IniConfigurationProvider carga la configuración desde pares clave-valor de archivo INI en tiempo de ejecución.

El código siguiente borra todos los proveedores de configuración y agrega varios:

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

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

                var env = hostingContext.HostingEnvironment;

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

                config.AddEnvironmentVariables();

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

En el código anterior, la configuración de los archivos MyIniConfig.ini y MyIniConfig.{Environment}.ini se reemplaza por la configuración de:

La descarga de ejemplo contiene el siguiente archivo MyIniConfig.ini:

MyKey="MyIniConfig.ini Value"

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

[Logging:LogLevel]
Default=Information
Microsoft=Warning

El siguiente código de la descarga de ejemplo muestra algunas de las configuraciones anteriores:

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

Proveedor de configuraciónJSON

JsonConfigurationProvider carga la configuración desde pares clave-valor de archivos 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:

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

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

El código anterior:

Por lo general, no conviene que un archivo JSON personalizado invalide los valores establecidos en el proveedor de configuración de variables de entorno ni en el proveedor de configuración de línea de comandos.

El código siguiente borra todos los proveedores de configuración y agrega varios:

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

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

                var env = hostingContext.HostingEnvironment;

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

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

                config.AddEnvironmentVariables();

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

En el código anterior, la configuración de los archivos MyConfig.json y MyConfig.Environment.json:

La descarga de ejemplo contiene el siguiente archivo MyConfig.json:

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

El siguiente código de la descarga de ejemplo muestra algunas de las configuraciones anteriores:

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

Proveedor de configuración XML

XmlConfigurationProvider carga la configuración desde pares clave-valor de archivo XML en tiempo de ejecución.

El código siguiente borra todos los proveedores de configuración y agrega varios:

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

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

                var env = hostingContext.HostingEnvironment;

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

                config.AddEnvironmentVariables();

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

En el código anterior, la configuración de los archivos MyXMLFile.xml y MyXMLFile.{Environment}.xml se reemplaza por la configuración de:

La descarga de ejemplo contiene el siguiente archivo MyXMLFile.xml:

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

El siguiente código de la descarga de ejemplo muestra algunas de las configuraciones anteriores:

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

Los elementos de repetición que usan el mismo nombre de elemento funcionan si el atributo name se usa para distinguir los elementos:

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

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

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 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 contiene 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((hostingContext, config) =>
{
    var path = Path.Combine(
        Directory.GetCurrentDirectory(), "path/to/files");
    config.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:

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

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

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

El siguiente código de la descarga de ejemplo muestra las opciones de configuración anteriores:

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

En el código anterior, config.AddInMemoryCollection(Dict) 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 la sección Proveedor de configuración JSON.

Consulte la sección Enlace de matrices para ver otro ejemplo que usa MemoryConfigurationProvider.

Configuración del punto de conexión de Kestrel

La configuración del punto de conexión específico de Kestrel invalida todas las configuraciones del punto de conexión entre servidores. Las configuraciones del punto de conexión entre servidores incluyen:

Tenga en cuenta el archivo siguiente appsettings.json usado en una aplicación web de ASP.NET Core:

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

Cuando el marcado resaltado anterior se usa en una aplicación web de ASP.NET Core y la aplicación se inicia en la línea de comandos con la siguiente configuración del punto de conexión entre servidores:

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

Kestrel se enlaza con el punto de conexión configurado específicamente para Kestrel en el archivo appsettings.json (https://localhost:9999) y no https://localhost:7777.

Considere el punto de conexión específico de Kestrel configurado como una variable de entorno:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

En la variable de entorno anterior, Https es el nombre del punto de conexión específico de Kestrel. En el archivo appsettings.json anterior también se define un punto de conexión específico de Kestrel denominado Https. De manera predeterminada, las variables de entorno que utilizan el proveedor de configuración de variables de entorno se leen después de appsettings.{Environment}.json, por lo tanto, la variable de entorno anterior se usa para el punto de conexión Https.

GetValue

ConfigurationBinder.GetValue extrae un único valor de la configuración con una clave determinada y lo convierte al tipo especificado: Este método es un método de extensión para 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}");
    }
}

En el código anterior, si NumberKey no se encuentra en la configuración, se usa el valor predeterminado de 99.

GetSection, GetChildren y Exists

Para los ejemplos siguientes, considere el siguiente archivo MySubsection.json:

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

El código siguiente agrega MySubsection.json a los proveedores de configuración:

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 devuelve una subsección de la configuración con la clave de subsección especificada.

El código siguiente devuelve los valores de 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"]}'");
    }
}

El código siguiente devuelve los valores de 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 nunca devuelve null. Si no se encuentra una sección que coincida, se devuelve una IConfigurationSection vacía.

Cuando GetSection devuelve una sección coincidente, Value no se rellena. Se devuelven Key y Path si la sección existe.

GetChildren y Exists

El código siguiente llama a IConfiguration.GetChildren y devuelve los valores de 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);
    }
}

El código anterior llama a ConfigurationExtensions.Exists para comprobar que la sección existe:

Enlace de matrices

ConfigurationBinder.Bind admite enlazar matrices a objetos con los índices de matriz en las claves de configuración. Cualquier formato de matriz que exponga un segmento de clave numérica es capaz de enlazar una matriz a una matriz de clase POCO.

Tenga en cuenta este archivo MyArray.json de la descarga de ejemplo:

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

El código siguiente agrega MyArray.json a los proveedores de configuración:

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

El código siguiente lee la configuración y muestra los valores:

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

El código anterior devuelve el siguiente resultado:

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

En el resultado anterior, el índice 3 tiene el valor value40, que corresponde a "4": "value40", en MyArray.json. Los índices de matriz enlazados son continuos y no están enlazados al índice de la clave de configuración. El enlazador de configuración no es capaz de enlazar los valores NULL ni de crear entradas NULL en objetos enlazados.

El código siguiente carga la configuración de array:entries con el método de extensión 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>();
            });
    }
}

El código siguiente lee la configuración de arrayDictDictionary y muestra los valores:

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

El código anterior devuelve el siguiente resultado:

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

El índice n.º 3 en el objeto enlazado contiene los datos de configuración para la clave de configuración array:4 y su valor de value4. Cuando se enlazan datos de configuración que contienen una matriz, los índices de la matriz en las claves de configuración se usan para iterar los datos de configuración al crear el objeto. No se puede conservar un valor NULL en los datos de configuración y no se crea una entrada con valores NULL en un objeto enlazado cuando una matriz en las claves de configuración omite uno o más índices.

Cualquier proveedor de configuración que lea el par clave-valor del índice n.º 3 puede proporcionar el elemento de configuración omitido para el índice n.º 3 antes del enlace a la instancia ArrayExample. Fíjese en el siguiente archivo Value3.json de la descarga de ejemplo:

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

En el código siguiente se incluye la configuración para Value3.json y arrayDictDictionary:

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

El código siguiente lee la configuración anterior y muestra los valores:

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

El código anterior devuelve el siguiente resultado:

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

Los proveedores de configuración personalizados no son necesarios para implementar el enlace de matriz.

Proveedores de configuración personalizada

La aplicación de ejemplo muestra cómo crear un proveedor de configuración básica que lee los pares clave-valor de configuración desde una base de datos mediante Entity Framework (EF).

El proveedor tiene las siguientes características:

  • La base de datos en memoria de EF se usa para fines de demostración. Para usar una base de datos que requiere una cadena de conexión, implemente un ConfigurationBuilder secundario para suministrar la cadena de conexión desde otro proveedor de configuración.
  • El proveedor lee una tabla de base de datos en la configuración en el inicio. El proveedor no consulta la base de datos por clave.
  • La función de recarga en cambio no se implementa, por lo que actualizar la base de datos después del inicio de la aplicación no afecta a la configuración de la aplicación.

Defina una entidad EFConfigurationValue para almacenar los valores de configuración en la base de datos.

Models/EFConfigurationValue.cs:

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

Agregue un EFConfigurationContext para almacenar y tener acceso a los valores configurados.

EFConfigurationProvider/EFConfigurationContext.cs:

// using Microsoft.EntityFrameworkCore;

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

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

Cree una clase que implemente 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);
    }
}

Cree el proveedor de configuración personalizado heredando de ConfigurationProvider. El proveedor de configuración inicializa la base de datos cuando está vacía. Puesto que las claves de configuración no distinguen entre mayúsculas y minúsculas, el diccionario empleado para iniciar la base de datos se crea con el comparador que tampoco hace tal distinción (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 método de extensión AddEFConfiguration permite agregar el origen de configuración 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));
    }
}

En el código siguiente se muestra cómo puede usar el EFConfigurationProvider personalizado en Program.cs:

// using Microsoft.EntityFrameworkCore;

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

Acceso a la configuración en métodos Startup

En el código siguiente se muestran los datos de configuración de los métodos 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();
        });
    }
}

Para ver un ejemplo de cómo acceder a la configuración mediante métodos de conveniencia de inicio, consulte Inicio de la aplicación: Métodos de conveniencia

Acceso a la configuración en Razor Pages

En el código siguiente se muestran los datos de configuración en una página de RazorPages:

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

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

En el siguiente código se agrega MyOptions al contenedor de servicios con Configure y se enlaza a la configuración:

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

    services.AddRazorPages();
}

En el marcado siguiente se usa la directiva @injectRazor para resolver y mostrar los valores de las opciones:

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

Acceso a la configuración en un archivo de vista de MVC

En el código siguiente se muestran los datos de configuración de una vista de MVC:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

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

Configurar opciones con un delegado

Las opciones configuradas en un delegado invalidan los valores establecidos en los proveedores de configuración.

La configuración de opciones con un delegado se muestra como ejemplo 2 en la aplicación de ejemplo.

En el código siguiente, se agrega un servicio IConfigureOptions<TOptions> al contenedor de servicios. Usa un delegado para configurar los valores de MyOptions:

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

    services.AddRazorPages();
}

En el código siguiente se muestran los valores de las opciones:

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

En el ejemplo anterior, los valores de Option1 y Option2 se especifican en appsettings.json y, luego, se reemplazan por el delegado configurado.

Configuración de host y de aplicación

Antes de configurar e iniciar la aplicación, se configura e inicia un host. El host es responsable de la administración del inicio y la duración de la aplicación. Tanto la aplicación como el host se configuran mediante los proveedores de configuración que se describen en este tema. Los pares clave-valor de configuración del host también se incluyen en la configuración de la aplicación. Para obtener más información sobre cómo se usan los proveedores de configuración cuando se compila el host y cómo afectan los orígenes de configuración a la configuración del host, consulte la información general sobre conceptos básicos de ASP.NET Core.

Configuración predeterminada del host

Para obtener más información sobre la configuración predeterminada al usar el host de web, vea la versión de este tema para ASP.NET Core 2.2.

  • La configuración del host la proporcionan los siguientes elementos:
    • Las variables de entorno con el prefijo DOTNET_ (por ejemplo, DOTNET_ENVIRONMENT) mediante el proveedor de configuración de variables de entorno. El prefijo (DOTNET_) se quita cuando se cargan los pares clave-valor de configuración.
    • Argumentos de la línea de comandos con el proveedor de configuración de línea de comandos.
  • La configuración predeterminada del host de web se ha establecido (ConfigureWebHostDefaults):
    • Kestrel se usa como el servidor web y se ha configurado mediante los proveedores de configuración de la aplicación.
    • Agregar el middleware de filtrado de host
    • Agregue el middleware de encabezados reenviados si la variable de entorno ASPNETCORE_FORWARDEDHEADERS_ENABLED se establece en true.
    • Habilite la integración con IIS.

Otra configuración

Este tema solo concierne a la configuración de aplicaciones. Otros aspectos de la ejecución y el hospedaje de aplicaciones ASP.NET Core se configuran mediante archivos de configuración que no se describen en este tema:

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

Para más información sobre cómo migrar la configuración de aplicaciones de versiones anteriores de ASP.NET, consulte Migrar de ASP.NET a ASP.NET Core.

Agregar configuración a partir de un ensamblado externo

Una implementación de IHostingStartup permite agregar mejoras a una aplicación al iniciarla a partir de un ensamblado externo fuera de la clase Startup de esta. Para obtener más información, consulte Uso de ensamblados de inicio de hospedaje en ASP.NET Core.

Recursos adicionales