Configuração no ASP.NET Core

Por Rick Anderson e Kirk Larkin

Observação

Esta não é a versão mais recente deste artigo. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Importante

Essas informações relacionam-se ao produto de pré-lançamento, que poderá ser substancialmente modificado antes do lançamento comercial. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.

Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

A configuração de aplicativos no ASP.NET Core é realizada usando um ou mais provedores de configuração. Os provedores de configuração leem os dados de configuração de pares chave-valor usando uma variedade de fontes de configuração:

  • Arquivos de configurações, como appsettings.json
  • Variáveis de ambiente
  • Azure Key Vault
  • Configuração de Aplicativos do Azure
  • Argumentos de linha de comando
  • Provedores personalizados, instalados ou criados
  • Arquivos de diretório
  • Objetos do .NET na memória

Este artigo fornece informações sobre configuração no ASP.NET Core. Para obter informações sobre como usar a configuração em aplicativos de console, confira Configuração do .NET.

Configuração de aplicativos e hosts

Aplicativos ASP.NET Core configuram e inicializam um host. O host é responsável pelo gerenciamento de tempo de vida e pela inicialização do aplicativo. Os modelos ASP.NET Core criam um WebApplicationBuilder que contém o host. Embora algumas configurações possam ser feitas tanto no host quanto nos provedores de configuração de aplicativos, em geral, apenas a configuração necessária para o host deve ser feita na configuração do host.

A configuração de aplicativos é a prioridade mais alta e é detalhada na próxima seção. A configuração de hosts segue a configuração de aplicativos e é descrita neste artigo.

Fontes de configuração de aplicativos padrão

Os aplicativos Web ASP.NET Core criados com dotnet new ou Visual Studio geram o seguinte código:

var builder = WebApplication.CreateBuilder(args);

O WebApplication.CreateBuilder inicializa uma nova instância da classe WebApplicationBuilder com os padrões pré-configurados. O WebApplicationBuilder (builder) inicializado fornece a configuração padrão para o aplicativo na seguinte ordem, da prioridade mais alta para a mais baixa:

  1. Argumentos de linha de comando usando o Provedor de configuração de linha de comando.
  2. Variáveis de ambiente não prefixadas usando o provedor de configuração de variáveis de ambiente não prefixadas.
  3. Segredos do usuário quando o aplicativo é executado no ambiente Development.
  4. appsettings.{Environment}.json usando o provedor de configuração JSON. Por exemplo, appsettings.Production.json e appsettings.Development.json.
  5. appsettings.json usando o provedor de configuração JSON.
  6. Um fallback para a configuração do host descrita na próxima seção.

Fontes de configuração de host padrão

A lista a seguir contém as fontes de configuração de host padrão da prioridade mais alta para a mais baixa para WebApplicationBuilder:

  1. Argumentos de linha de comando usando o provedor de configuração de linha de comando
  2. Variáveis ​​de ambiente prefixadas pelo DOTNET_ usando o provedor de configuração de variáveis ​​de ambiente.
  3. Variáveis ​​de ambiente prefixadas pelo ASPNETCORE_ usando o provedor de configuração de variáveis ​​de ambiente.

Para o .NET Generic Host e Host da Web, as fontes de configuração de host padrão da prioridade mais alta para a mais baixa são:

  1. Variáveis ​​de ambiente prefixadas pelo ASPNETCORE_ usando o provedor de configuração de variáveis ​​de ambiente.
  2. Argumentos de linha de comando usando o provedor de configuração de linha de comando
  3. Variáveis ​​de ambiente prefixadas pelo DOTNET_ usando o provedor de configuração de variáveis ​​de ambiente.

Quando um valor de configuração é definido na configuração do host e do aplicativo, a configuração do aplicativo é usada.

Variáveis do host

As seguintes variáveis são bloqueadas antecipadamente ao inicializar os construtores de host e não podem ser influenciadas pela configuração do aplicativo:

Todas as outras configurações de host são lidas da configuração do aplicativo em vez da configuração do host.

URLS é uma das muitas configurações de host comuns que não é uma configuração de inicialização. Como todas as outras configurações de host que não estão na lista anterior, URLS é lida posteriormente na configuração do aplicativo. A configuração do host é um fallback para a configuração do aplicativo, portanto, a configuração do host pode ser usada para definir URLS, mas será substituída por qualquer fonte de configuração na configuração do aplicativo como appsettings.json.

Para obter mais informações, confira Alterar a raiz do conteúdo, o nome do aplicativo e o ambiente e Alterar a raiz do conteúdo, o nome do aplicativo e o ambiente por variáveis de ambiente ou linha de comando

As seções restantes neste artigo referem-se à configuração de aplicativos.

Provedores de configuração de aplicativos

O código a seguir exibe os provedores de configuração habilitados na ordem em que foram adicionados:

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

A lista anterior das fontes de configuração padrão de prioridade mais alta para a mais baixa mostra os provedores na ordem oposta em que são adicionados ao aplicativo gerado pelo modelo. Por exemplo, o provedor de configuração JSON é adicionado antes do provedor de configuração de linha de comando.

Os provedores de configuração adicionados posteriormente têm prioridade mais alta e substituem as configurações de chave anteriores. Por exemplo, se MyKey estiver configurado em appsettings.json e no ambiente, o valor do ambiente será usado. Usando os provedores de configuração padrão, o provedor de configuração de linha de comando substitui todos os outros provedores.

Para obter mais informações sobre CreateBuilder, confira Configurações do construtor padrão.

appsettings.json

Considere o seguinte arquivo appsettings.json:

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

O código a seguir do download de exemplo exibe várias das configurações 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}");
    }
}

O padrão JsonConfigurationProvider carrega a configuração na seguinte ordem:

  1. appsettings.json
  2. appsettings.{Environment}.json : por exemplo, os arquivos appsettings.Production.json e appsettings.Development.json. A versão do ambiente do arquivo é carregada com base no IHostingEnvironment.EnvironmentName. Para obter mais informações, confira Usar vários ambientes no ASP.NET Core.

Os valores de appsettings.{Environment}.json substituem as chaves em appsettings.json. Por exemplo, por padrão:

  • No desenvolvimento, a configuração de appsettings.Development.json substitui os valores encontrados em appsettings.json.
  • Na produção, a configuração de appsettings.Production.json substitui os valores encontrados em appsettings.json. Por exemplo, ao implantar o aplicativo no Azure.

Se um valor de configuração deve ser assegurado, confira GetValue. O exemplo anterior lê apenas cadeias de caracteres e não dá suporte a um valor padrão.

Usando a configuração padrão, os arquivos appsettings.json e appsettings.{Environment}.json são habilitados com reloadOnChange: true. As alterações feitas no arquivo appsettings.json e appsettings.{Environment}.jsonapós a inicialização do aplicativo são lidas pelo provedor de configuração ONJS.

Comentários no appsettings.json

Comentários em arquivos appsettings.json e appsettings.{Environment}.json são suportados usando comentários no estilo JavaScript ou C#.

Vincular dados de configuração hierárquica usando o padrão de opções

A maneira preferencial de ler os valores de configuração relacionados é usando o padrão de opções. Por exemplo, para ler os seguintes valores de configuração:

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

Crie a seguinte classe PositionOptions:

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

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

Uma classe de opções:

  • Deve ser não abstrata e com um construtor público sem parâmetros.
  • Todas as propriedades públicas de leitura e gravação do tipo são vinculadas.
  • Os campos não são vinculados. No código anterior, Position não está vinculado. O campo Position é usado para que a cadeia de caracteres "Position" não precise ser codificada no aplicativo ao associar a classe a um provedor de configuração.

O seguinte código:

  • Chama ConfigurationBinder.Bind para associar a classe PositionOptions à seção Position.
  • Exibe os dados de configuração 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}");
    }
}

No código anterior, por padrão, as alterações no arquivo de configuração JSON após a inicialização do aplicativo são lidas.

ConfigurationBinder.Get<T> associa e retorna o tipo especificado. ConfigurationBinder.Get<T> pode ser mais conveniente do que usar ConfigurationBinder.Bind. O código a seguir mostra como usar ConfigurationBinder.Get<T> com a classe PositionOptions:

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

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

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

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

No código anterior, por padrão, as alterações no arquivo de configuração JSON após a inicialização do aplicativo são lidas.

Uma abordagem alternativa ao usar o padrão de opções é associar a seção Position e adicioná-la ao contêiner do serviço de injeção de dependência. No código a seguir, PositionOptions é adicionada ao contêiner de serviço com Configure e associada à configuração:

using ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

Usando o código anterior, o código a seguir lê as opções de posição:

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

No código anterior, as alterações no arquivo de configuração JSON após a inicialização do aplicativo não são lidas. Para ler as alterações após a inicialização do aplicativo, use IOptionsSnapshot.

Usando a configuração padrão, os arquivos appsettings.json e appsettings.{Environment}.json são habilitados com reloadOnChange: true. As alterações feitas no arquivo appsettings.json e appsettings.{Environment}.jsonapós a inicialização do aplicativo são lidas pelo provedor de configuração ONJS.

Confira Provedor de configuração JSON neste documento para obter informações sobre como adicionar arquivos de configuração JSON adicionais.

Como combinar a coleção de serviços

Considere o seguinte ao registrar serviços e configurar opções:

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

Grupos de registros relacionados podem ser movidos para um método de extensão para registrar serviços. Por exemplo, os serviços de configuração são adicionados à seguinte classe:

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

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

            return services;
        }

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

            return services;
        }
    }
}

Os serviços restantes são registrados em uma classe similar. O código a seguir usa os novos métodos de extensão para registrar os serviços:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

Observação: Cada método de extensão services.Add{GROUP_NAME} adiciona e possivelmente configura serviços. Por exemplo, AddControllersWithViews adiciona os serviços que os controladores MVC com visualizações requerem e AddRazorPages adiciona os serviços que o Razor Pages requer.

Segurança e segredos do usuário

Diretrizes de dados de configuração:

  • Nunca armazene senhas ou outros dados confidenciais no código do provedor de configuração ou nos arquivos de configuração de texto sem formatação. A ferramenta Gerenciador de Segredos pode ser usada para armazenar segredos em desenvolvimento.
  • Não use segredos de produção em ambientes de teste ou de desenvolvimento.
  • Especifique segredos fora do projeto para que eles não sejam acidentalmente comprometidos com um repositório de código-fonte.

Por padrão, a fonte de configuração de segredos do usuário é registrada após as fontes de configuração JSON. Portanto, as chaves de segredos do usuário têm precedência sobre as chaves em appsettings.json e appsettings.{Environment}.json.

Para obter mais informações sobre como armazenar senhas ou outros dados confidenciais:

O Azure Key Vault armazena os segredos do aplicativo com segurança para aplicativos ASP.NET Core. Para obter mais informações, confira Provedor de configuração do Azure Key Vault no ASP.NET Core.

Variáveis de ambiente não prefixadas

Variáveis de ambiente não prefixadas são variáveis de ambiente diferentes daquelas prefixadas por ASPNETCORE_ ou DOTNET_. Por exemplo, os modelos de aplicativo Web ASP.NET Core definem "ASPNETCORE_ENVIRONMENT": "Development" em launchSettings.json. Para obter mais informações sobre variáveis de ambiente ASPNETCORE_ e DOTNET_, confira:

Usando a configuração padrão, o EnvironmentVariablesConfigurationProvider carrega a configuração dos pares chave-valor da variável de ambiente depois de ler appsettings.json, appsettings.{Environment}.json, e segredos do usuário. Portanto, os valores de chave lidos do ambiente substituem os valores lidos de appsettings.json, appsettings.{Environment}.json e segredos do usuário.

O separador : não funciona com chaves hierárquicas de variáveis de ambiente em todas as plataformas. __, o sublinhado duplo, tem:

  • Suporte em todas as plataformas. Por exemplo, o separador : não tem suporte pelo Bash, mas pelo __ tem.
  • Substituição automática por um :

Os seguintes comandos set:

  • Defina as chaves de ambiente e os valores do exemplo anterior no Windows.
  • Teste as configurações ao usar o download de exemplo. O comando dotnet run precisa ser executado no diretório do projeto.
set MyKey="My key from Environment"
set Position__Title=Environment_Editor
set Position__Name=Environment_Rick
dotnet run

As configurações de ambiente anteriores:

  • São definidas apenas em processos iniciados por meio da janela de comando em que foram definidos.
  • Não serão lidos por navegadores iniciados com o Visual Studio.

Os comandos setx a seguir podem ser usados para definir as chaves de ambiente e os valores no Windows. Diferente de set, as configurações setx são persistentes. /M define a variável no ambiente do sistema. Se o comutador /M não for usado, uma variável de ambiente do usuário será definida.

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

Para testar se os comandos anteriores substituem appsettings.json e appsettings.{Environment}.json:

  • Com o Visual Studio: saia e reinicie o Visual Studio.
  • Com a CLI: inicie uma nova janela de comando e insira dotnet run.

Chame AddEnvironmentVariables com uma cadeia de caracteres a fim de especificar um prefixo para variáveis de ambiente:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

No código anterior:

O prefixo é removido quando os pares de valores-chave de configuração são lidos.

Estes comandos testam o prefixo 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

A configuração padrão carrega variáveis de ambiente e argumentos de linha de comando prefixados com DOTNET_ e ASPNETCORE_. Os prefixos DOTNET_ e ASPNETCORE_ são usados pelo ASP.NET Core para configuração de host e aplicativo, mas não para configuração de usuário. Para obter mais informações sobre configuração de host e aplicativo, confira Host genérico do .NET.

Em Serviço de Aplicativo do Azure, selecione Nova configuração de aplicativo na página Configuração > Configurações. As configurações do aplicativo do Serviço de Aplicativo do Azure são:

  • Criptografadas em repouso e transmitidas por um canal criptografado.
  • Expostas como variáveis de ambiente.

Para saber mais, confira Aplicativos do Azure: substituir a configuração do aplicativo usando o portal do Azure.

Confira Prefixos de cadeia de conexão para obter informações sobre cadeias de conexão de banco de dados do Azure.

Nomenclatura de variáveis de ambiente

Os nomes das variáveis de ambiente refletem a estrutura de um arquivo appsettings.json. Cada elemento na hierarquia é separado por um sublinhado duplo (preferível) ou dois pontos. Quando a estrutura do elemento inclui uma matriz, o índice da matriz deve ser tratado como um nome de elemento adicional neste caminho. Considere o arquivo appsettings.json a seguir e seus valores equivalentes representados como variáveis de ambiente.

appsettings.json

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

variáveis de ambiente

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

Variáveis de ambiente definidas no launchSettings.json gerado

As variáveis de ambiente definidas em launchSettings.json substituem as definidas no ambiente do sistema. Por exemplo, os modelos da Web do ASP.NET Core geram um arquivo launchSettings.json que define a configuração do ponto de extremidade para:

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

A configuração de applicationUrl define a variável de ambiente ASPNETCORE_URLS e substitui os valores definidos no ambiente.

Variáveis de ambiente de escape no Linux

No Linux, o valor das variáveis de ambiente de URL deve ser escapado para que systemd possa analisá-lo. Use o ferramenta linux systemd-escape que suspende http:--localhost:5001

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

Exibir variáveis de ambiente

O código a seguir exibe as variáveis e valores de ambiente na inicialização do aplicativo, o que pode ser útil ao depurar as configurações do ambiente:

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

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

Linha de comando

Usando a configuração padrão, o CommandLineConfigurationProvider carrega a configuração dos pares chave-valor do argumento da linha de comando após as seguintes fontes de configuração:

  • Arquivos appsettings.json e appsettings.{Environment}.json.
  • Segredos do aplicativo no ambiente de desenvolvimento.
  • Variáveis de ambiente.

Por padrão, os valores de configuração definidos na linha de comando substituem os valores de configuração definidos com todos os outros provedores de configuração.

Argumentos de linha de comando

O comando a seguir define chaves e valores usando =:

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

O comando a seguir define chaves e valores usando /:

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

O comando a seguir define chaves e valores usando --:

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

O valor da chave:

  • Deve seguir =, ou a chave deve ter um prefixo de -- ou / quando o valor vier após um espaço.
  • Não é necessário se = for usado. Por exemplo, MySetting=.

No mesmo comando, não combine pares chave-valor do argumento de linha de comando que usam um sinal de =l com pares chave-valor que usam um espaço.

Mapeamentos de comutador

Os mapeamentos de comutador permitem fornecer a lógica de substituição do nome da chave. Forneça um dicionário de substituições de comutador para o método AddCommandLine.

Ao ser usado, o dicionário de mapeamentos de comutador é verificado para oferecer uma chave que corresponda à chave fornecida por um argumento de linha de comando. Se a chave de linha de comando for encontrada no dicionário, o valor do dicionário será passado de volta para definir o par chave-valor na configuração do aplicativo. Um mapeamento de comutador é necessário para qualquer chave de linha de comando prefixada com um traço único (-).

Regras de chave do dicionário de mapeamentos de comutador:

  • Os comutadores devem iniciar com - ou --.
  • O dicionário de mapeamentos de comutador chave não deve conter chaves duplicadas.

Para usar um dicionário de mapeamentos de comutador, passe-o para a chamada para 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();

Execute o seguinte comando para testar a substituição da chave:

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

O código a seguir mostra os valores de chave para as chaves substituídas:

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

Para aplicativos que usam mapeamentos de opção, a chamada CreateDefaultBuilder para não deve passar argumentos. A chamada AddCommandLine do método CreateDefaultBuilder não inclui opções mapeadas, e não é possível passar o dicionário de mapeamento de opções para CreateDefaultBuilder. A solução não é passar os argumentos para CreateDefaultBuilder, mas, em vez disso, permitir que o método AddCommandLine do método ConfigurationBuilder processe os dois argumentos e o dicionário de mapeamento de opções.

Definir ambiente e argumentos de linha de comando com o Visual Studio

Os argumentos de ambiente e linha de comando podem ser definidos no Visual Studio na caixa de diálogo de perfis de inicialização:

  • No Gerenciador de Soluções, clique com o botão direito do mouse no projeto e selecione Propriedades.
  • Selecione Depurar > Geral e Abrir depuração dos perfis de inicialização da IU.

Dados de configuração hierárquica

A API de configuração lê os dados de configuração hierárquica nivelando os dados hierárquicos com o uso de um delimitador nas chaves de configuração.

O download de exemplo contém o seguinte arquivo appsettings.json:

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

O código a seguir do download de exemplo exibe várias das configurações:

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

A maneira preferencial de ler dados de configuração hierárquica é usando o padrão de opções. Para obter mais informações, confira Vincular dados de configuração hierárquica neste documento.

Os métodos GetSection e GetChildren estão disponíveis para isolar as seções e os filhos de uma seção nos dados de configuração. Esses métodos serão descritos posteriormente em GetSection, GetChildren e Exists.

Teclas de configuração e valores

Teclas de configuração:

  • Não diferencia maiúsculas e minúsculas. Por exemplo, ConnectionString e connectionstring são tratados como chaves equivalentes.
  • Se uma chave e um valor forem definidos em mais de um provedor de configuração, será usado o valor do último provedor adicionado. Para obter mais informações, confira Configuração padrão.
  • Chaves hierárquicas
    • Ao interagir com a API de configuração, um separador de dois-pontos (:) funciona em todas as plataformas.
    • Nas variáveis de ambiente, talvez um separador de dois-pontos não funcione em todas as plataformas. Um sublinhado duplo, __, é compatível com todas as plataformas e é convertido automaticamente em dois-pontos :.
    • No Azure Key Vault, as chaves hierárquicas usam -- como separador. O provedor de configuração do Azure Key Vault substitui automaticamente -- por : quando os segredos são carregados na configuração do aplicativo.
  • O ConfigurationBinder dá suporte a matrizes de associação para objetos usando os índices em chaves de configuração. A associação de matriz está descrita na seção Associar uma matriz a uma classe.

Valores de configuração:

  • são cadeias de caracteres.
  • Não é possível armazenar valores nulos na configuração ou associá-los a objetos.

Provedores de configuração

A tabela a seguir mostra os provedores de configuração disponíveis para aplicativos ASP.NET Core.

Provedor Fornece a configuração de
Provedor de configuração do Azure Key Vault Cofre de Chave do Azure
Provedor de configuração do Aplicativo do Azure Configuração de Aplicativo do Azure
Provedor de configuração de linha de comando Parâmetros de linha de comando
Provedor de Configuração personalizado Fonte personalizada
Provedor de configuração de variáveis de ambiente Variáveis de ambiente
Provedor de configuração de arquivo Arquivos INI, JSON e XML
Provedor de configuração de chave por arquivo Arquivos de diretório
Provedor de configuração de memória Coleções na memória
Segredos do usuário Arquivo no diretório de perfil do usuário

As fontes de configuração são lidas na ordem especificada pelos provedores de configuração. Solicite provedores de configuração em código para atender às prioridades das fontes de configuração subjacentes exigidas pelo aplicativo.

Uma sequência comum de provedores de configuração é:

  1. appsettings.json
  2. appsettings.{Environment}.json
  3. Segredos do usuário
  4. Variáveis de ambiente usando o Provedor de configuração de variáveis de ambiente.
  5. Argumentos de linha de comando usando o Provedor de configuração de linha de comando.

Uma prática comum é adicionar o provedor de configuração de linha de comando por último em uma série de provedores, a fim de permitir que os argumentos de linha de comando substituam a configuração definida por outros provedores.

A sequência anterior de provedores é usada na configuração padrão.

Prefixos de cadeia de conexão

A API de configuração tem regras de processamento especiais para quatro variáveis de ambiente de cadeia de conexão. Essas cadeias de conexão estão envolvidas na configuração de cadeias de conexão do Azure para o ambiente do aplicativo. As variáveis de ambiente com os prefixos mostrados na tabela são carregadas no aplicativo com a configuração padrão ou quando nenhum prefixo é fornecido ao AddEnvironmentVariables.

Prefixo da cadeia de conexão Provedor
CUSTOMCONNSTR_ Provedor personalizado
MYSQLCONNSTR_ MySQL
SQLAZURECONNSTR_ Banco de Dados SQL do Azure
SQLCONNSTR_ SQL Server

Quando uma variável de ambiente for descoberta e carregada na configuração com qualquer um dos quatro prefixos mostrados na tabela:

  • A chave de configuração é criada removendo o prefixo da variável de ambiente e adicionando uma seção de chave de configuração (ConnectionStrings).
  • Um novo par chave-valor de configuração é criado para representar o provedor de conexão de banco de dados (exceto para CUSTOMCONNSTR_, que não tem um provedor indicado).
Chave de variável de ambiente Chave de configuração convertida Entrada de configuração do provedor
CUSTOMCONNSTR_{KEY} ConnectionStrings:{KEY} Entrada de configuração não criada.
MYSQLCONNSTR_{KEY} ConnectionStrings:{KEY} Chave: ConnectionStrings:{KEY}_ProviderName:
Valor: MySql.Data.MySqlClient
SQLAZURECONNSTR_{KEY} ConnectionStrings:{KEY} Chave: ConnectionStrings:{KEY}_ProviderName:
Valor: System.Data.SqlClient
SQLCONNSTR_{KEY} ConnectionStrings:{KEY} Chave: ConnectionStrings:{KEY}_ProviderName:
Valor: System.Data.SqlClient

Provedor de configuração de arquivo

FileConfigurationProvider é a classe base para carregamento da configuração do sistema de arquivos. Os seguintes provedores de configuração derivam de FileConfigurationProvider:

Provedor de configuração INI

O IniConfigurationProvider carrega a configuração de pares chave-valor do arquivo INI em runtime.

O código a seguir adiciona vários provedores de configuração:

var builder = WebApplication.CreateBuilder(args);

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

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

builder.Services.AddRazorPages();

var app = builder.Build();

No código anterior, as configurações nos arquivos MyIniConfig.ini e MyIniConfig.{Environment}.ini são substituídas pelas configurações no:

O download de exemplo contém o seguinte arquivo MyIniConfig.ini:

MyKey="MyIniConfig.ini Value"

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

[Logging:LogLevel]
Default=Information
Microsoft=Warning

O código a seguir do download de exemplo exibe várias das configurações 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}");
    }
}

Provedor de configuração JSON

O JsonConfigurationProvider carrega a configuração dos pares de valores-chave do arquivo JSON.

As sobrecargas podem especificar:

  • Se o arquivo é opcional.
  • Se a configuração será recarregada caso o arquivo seja alterado.

Considere o seguinte código:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

O código anterior:

Normalmente, você não deseja um arquivo JSON personalizado substituindo os valores definidos no provedor de configuração de variáveis de ambiente e no provedor de configuração de linha de comando.

Provedor de configuração XML

O XmlConfigurationProvider carrega a configuração de pares chave-valor do arquivo XML em runtime.

O código a seguir adiciona vários provedores de configuração:

var builder = WebApplication.CreateBuilder(args);

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

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

builder.Services.AddRazorPages();

var app = builder.Build();

No código anterior, as configurações nos arquivos MyXMLFile.xml e MyXMLFile.{Environment}.xml são substituídas pelas configurações no:

O download de exemplo contém o seguinte arquivo 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>

O código a seguir do download de exemplo exibe várias das configurações 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}");
    }
}

Elementos repetidos que usam o mesmo nome de elemento funcionarão se o atributo name for usado para diferenciar os 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>

O código a seguir lê o arquivo de configuração anterior e exibe as chaves e os 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"
                       );
    }
}

É possível usar atributos para fornecer valores:

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

O arquivo de configuração anterior carrega as seguintes chaves com value:

  • key:attribute
  • section:key:attribute

Provedor de configuração de chave por arquivo

O KeyPerFileConfigurationProvider usa arquivos do diretório como pares chave-valor de configuração. A chave é o nome do arquivo. O valor contém o conteúdo do arquivo. O provedor de configuração de chave por arquivo é usado em cenários de hospedagem do Docker.

Para ativar a configuração de chave por arquivo, chame o método de extensão AddKeyPerFile em uma instância do ConfigurationBuilder. O directoryPath para os arquivos deve ser um caminho absoluto.

As sobrecargas permitem especificar:

  • Um delegado Action<KeyPerFileConfigurationSource> que configura a origem.
  • Se o diretório é opcional, e o caminho para o diretório.

O sublinhado duplo (__) é usado como um delimitador de chave de configuração em nomes de arquivo. Por exemplo, o nome do arquivo Logging__LogLevel__System produz a chave de configuração Logging:LogLevel:System.

Chame ConfigureAppConfiguration ao criar o host para especificar a configuração do aplicativo:

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

Provedor de configuração de memória

O MemoryConfigurationProvider usa uma coleção na memória como pares chave-valor de configuração.

O código a seguir adiciona uma coleção de memória ao sistema de configuração:

var builder = WebApplication.CreateBuilder(args);

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

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

builder.Services.AddRazorPages();

var app = builder.Build();

O código a seguir do download de exemplo exibe as configurações 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}");
    }
}

No código anterior, config.AddInMemoryCollection(Dict) é adicionado após os provedores de configuração padrão. Para obter um exemplo de ordenação dos provedores de configuração, confira o provedor de configuração JSON.

Confira Associar uma matriz para outro exemplo usando MemoryConfigurationProvider.

configuração do ponto de extremidade Kestrel

configuração de ponto de extremidade específica Kestrel substitui todas as configurações de ponto de extremidade entre servidores. As configurações de ponto de extremidade entre servidores incluem:

Considere o seguinte arquivo appsettings.json usado em um aplicativo Web ASP.NET Core:

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

Quando a marcação realçada anterior é usada em um aplicativo Web ASP.NET Core e o aplicativo é iniciado na linha de comando com a seguinte configuração de ponto de extremidade entre servidores:

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

Kestrel se liga ao ponto de extremidade configurado especificamente para Kestrel no arquivo appsettings.json (https://localhost:9999) e não no https://localhost:7777.

Considere o ponto de extremidade específico Kestrel configurado como uma variável de ambiente:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

Na variável de ambiente anterior, Https é o nome do ponto de extremidade específico do Kestrel. O arquivo appsettings.json anterior também define um ponto de extremidade específico Kestrel chamado Https. Por padrão, as variáveis de ambiente que usam o provedor de configuração de variáveis de ambiente são lidas após appsettings.{Environment}.json, portanto, a variável de ambiente anterior é usada para o ponto de extremidade Https.

GetValue

ConfigurationBinder.GetValue extrai um valor de configuração com uma chave especificada e o converte para o 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}");
    }
}

No código anterior, se NumberKey não for encontrado na configuração, será usado o valor padrão 99.

GetSection, GetChildren e Exists

Para os exemplos a seguir, considere o seguinte arquivo MySubsection.json:

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

O código a seguir adiciona MySubsection.json aos provedores de configuração:

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

GetSection

IConfiguration.GetSection returna uma subseção de configuração com a chave de subseção especificada.

O código a seguir retorna valores para 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"]}'");
    }
}

O código a seguir retorna valores para 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 retorna null. Se uma seção correspondente não for encontrada, um IConfigurationSection vazio será retornado.

Quando GetSection retorna uma seção correspondente, Value não é preenchido. Key e Path são retornados quando a seção existe.

GetChildren e Exists

O código a seguir chama IConfiguration.GetChildren e retorna valores para 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);
    }
}

O código anterior chama ConfigurationExtensions.Exists para verificar se a seção existe:

Associar uma matriz

O ConfigurationBinder.Bind dá suporte a matrizes de associação para objetos usando os índices em chaves de configuração. Qualquer formato de matriz que exponha um segmento de chave numérica é capaz de associar matrizes a uma matriz de classe POCO.

Considere MyArray.json do download de exemplo:

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

O código a seguir adiciona MyArray.json aos provedores de configuração:

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

O código a seguir lê a configuração e exibe os 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; } 
}

O código anterior retorna a saída a seguir:

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

Na saída anterior, o Índice 3 tem valor value40, correspondendo a "4": "value40", no MyArray.json. Os índices de matriz vinculados são contínuos e não vinculados ao índice de chave de configuração. O associador de configuração não é capaz de vincular valores nulos ou criar entradas nulas em objetos vinculados.

Provedor de Configuração personalizado

O aplicativo de exemplo demonstra como criar um provedor de configuração básico que lê os pares chave-valor da configuração de um banco de dados usando Entity Framework (EF).

O provedor tem as seguintes características:

  • O banco de dados EF na memória é usado para fins de demonstração. Para usar um banco de dados que exija uma cadeia de conexão, implemente um ConfigurationBuilder secundário para fornecer a cadeia de conexão de outro provedor de configuração.
  • O provedor lê uma tabela de banco de dados na configuração na inicialização. O provedor não consulta o banco de dados em uma base por chave.
  • O recarregamento na alteração não está implementado, portanto, a atualização do banco de dados após a inicialização do aplicativo não tem efeito sobre a configuração do aplicativo.

Defina uma entidade EFConfigurationValue para armazenar valores de configuração no banco de dados.

Models/EFConfigurationValue.cs:

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

Adicione um EFConfigurationContext para armazenar e acessar os valores configurados.

EFConfigurationProvider/EFConfigurationContext.cs:

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

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

Crie uma classe que implementa 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);
}

Crie o provedor de configuração personalizado através da herança de ConfigurationProvider. O provedor de configuração inicializa o banco de dados quando ele está vazio. Como as chaves de configuração não diferenciam maiúsculas de minúsculas, o dicionário usado para inicializar o banco de dados é criado com o comparador que não diferencia maiúsculas de minúsculas (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;
    }
}

Um método de extensão AddEFConfiguration permite adicionar a fonte de configuração a um ConfigurationBuilder.

Extensions/EntityFrameworkExtensions.cs:

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

O código a seguir mostra como usar o EFConfigurationProvider personalizado no Program.cs :

//using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

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

var app = builder.Build();

app.Run();

Configuração de acesso com injeção de dependência (DI)

A configuração pode ser injetada em serviços usando a injeção de dependência (DI) resolvendo o serviço IConfiguration:

public class Service
{
    private readonly IConfiguration _config;

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

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

        // ...
    }
}

Para obter informações sobre como acessar valores usando IConfiguration, confira GetValue e GetSection, GetChildren e Exists neste artigo.

Acessar configuração no Razor Pages

O código a seguir exibe os dados de configuração em um Razor Page:

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

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

No código a seguir, MyOptions é adicionada ao contêiner de serviço com Configure e associada à configuração:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

A marcação a seguir usa a diretiva @injectRazor para resolver e exibir os valores de opções:

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

Acessar a configuração em um arquivo de visualização MVC

O código a seguir exibe os dados de configuração em uma visualização MVC:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

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

Acessar a configuração no Program.cs

O código a seguir acessa a configuração no arquivo Program.cs.

var builder = WebApplication.CreateBuilder(args);

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

var app = builder.Build();

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

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

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

app.Run();

No appsettings.json para o exemplo anterior:

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

Configurar opções com um delegado

As opções configuradas em um delegado substituem os valores definidos nos provedores de configuração.

No código a seguir, um serviço IConfigureOptions<TOptions> é adicionado ao contêiner de serviço. Ele usa um delegado para configurar valores para 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();

O código a seguir exibe os valores das opções:

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

No exemplo anterior, os valores de Option1 e Option2 são especificados em appsettings.json e substituídos pelo delegado configurado.

Configuração do host versus do aplicativo

Antes do aplicativo ser configurado e iniciado, um host é configurado e iniciado. O host é responsável pelo gerenciamento de tempo de vida e pela inicialização do aplicativo. O aplicativo e o host são configurados usando os provedores de configuração descritos neste tópico. Os pares chave-valor de configuração do host também estão incluídos na configuração do aplicativo. Para obter mais informações sobre como os provedores de configuração são usados quando o host é compilado e como as fontes de configuração afetam a configuração do host, confira Visão geral dos fundamentos do ASP.NET Core.

Configuração de host padrão

Para obter detalhes sobre a configuração padrão ao usar o host da Web, confira a versão do ASP.NET Core 2.2 deste tópico.

  • A configuração do host é fornecida de:
  • A configuração padrão do host da Web foi estabelecida (ConfigureWebHostDefaults):
    • O Kestrel é usado como o servidor Web e configurado usando provedores de configuração do aplicativo.
    • Adicione o middleware de filtragem de host.
    • Adicione o middleware de cabeçalhos encaminhados se a variável de ambiente ASPNETCORE_FORWARDEDHEADERS_ENABLED for definida para true.
    • Habilite a integração de IIS.

Outra configuração

Este tópico refere-se apenas à configuração do aplicativo. Outros aspectos da execução e hospedagem de aplicativos ASP.NET Core são configurados usando arquivos de configuração não abordados neste tópico:

As variáveis de ambiente definidas em launchSettings.json substituem as definidas no ambiente do sistema.

Para saber mais sobre como migrar a configuração do aplicativo de versões anteriores do ASP.NET, confira Atualizar do ASP.NET para o ASP.NET Core.

Adicionar configuração de um assembly externo

Uma implementação IHostingStartup permite adicionar melhorias a um aplicativo durante a inicialização de um assembly externo fora da classe Startup do aplicativo. Para obter mais informações, confira Usar assemblies de inicialização de hospedagem no ASP.NET Core.

Gerador de origem para configuração da associação

O gerador de origem da associação de configuração fornece AOT e configuração de corte amigável. Para obter mais informações, consulte Gerador de origem da associação de configuração.

Recursos adicionais

A configuração de aplicativos no ASP.NET Core é realizada usando um ou mais provedores de configuração. Os provedores de configuração leem os dados de configuração de pares chave-valor usando uma variedade de fontes de configuração:

  • Arquivos de configurações, como appsettings.json
  • Variáveis de ambiente
  • Azure Key Vault
  • Configuração de Aplicativos do Azure
  • Argumentos de linha de comando
  • Provedores personalizados, instalados ou criados
  • Arquivos de diretório
  • Objetos do .NET na memória

Este artigo fornece informações sobre configuração no ASP.NET Core. Para obter informações sobre como usar a configuração em aplicativos de console, confira Configuração do .NET.

Configuração de aplicativos e hosts

Aplicativos ASP.NET Core configuram e inicializam um host. O host é responsável pelo gerenciamento de tempo de vida e pela inicialização do aplicativo. Os modelos ASP.NET Core criam um WebApplicationBuilder que contém o host. Embora algumas configurações possam ser feitas tanto no host quanto nos provedores de configuração de aplicativos, em geral, apenas a configuração necessária para o host deve ser feita na configuração do host.

A configuração de aplicativos é a prioridade mais alta e é detalhada na próxima seção. A configuração de hosts segue a configuração de aplicativos e é descrita neste artigo.

Fontes de configuração de aplicativos padrão

Os aplicativos Web ASP.NET Core criados com dotnet new ou Visual Studio geram o seguinte código:

var builder = WebApplication.CreateBuilder(args);

O WebApplication.CreateBuilder inicializa uma nova instância da classe WebApplicationBuilder com os padrões pré-configurados. O WebApplicationBuilder (builder) inicializado fornece a configuração padrão para o aplicativo na seguinte ordem, da prioridade mais alta para a mais baixa:

  1. Argumentos de linha de comando usando o Provedor de configuração de linha de comando.
  2. Variáveis de ambiente não prefixadas usando o provedor de configuração de variáveis de ambiente não prefixadas.
  3. Segredos do usuário quando o aplicativo é executado no ambiente Development.
  4. appsettings.{Environment}.json usando o provedor de configuração JSON. Por exemplo, appsettings.Production.json e appsettings.Development.json.
  5. appsettings.json usando o provedor de configuração JSON.
  6. Um fallback para a configuração do host descrita na próxima seção.

Fontes de configuração de host padrão

A lista a seguir contém as fontes de configuração de host padrão da prioridade mais alta para a mais baixa para WebApplicationBuilder:

  1. Argumentos de linha de comando usando o provedor de configuração de linha de comando
  2. Variáveis ​​de ambiente prefixadas pelo DOTNET_ usando o provedor de configuração de variáveis ​​de ambiente.
  3. Variáveis ​​de ambiente prefixadas pelo ASPNETCORE_ usando o provedor de configuração de variáveis ​​de ambiente.

Para o .NET Generic Host e Host da Web, as fontes de configuração de host padrão da prioridade mais alta para a mais baixa são:

  1. Variáveis ​​de ambiente prefixadas pelo ASPNETCORE_ usando o provedor de configuração de variáveis ​​de ambiente.
  2. Argumentos de linha de comando usando o provedor de configuração de linha de comando
  3. Variáveis ​​de ambiente prefixadas pelo DOTNET_ usando o provedor de configuração de variáveis ​​de ambiente.

Quando um valor de configuração é definido na configuração do host e do aplicativo, a configuração do aplicativo é usada.

Variáveis do host

As seguintes variáveis são bloqueadas antecipadamente ao inicializar os construtores de host e não podem ser influenciadas pela configuração do aplicativo:

Todas as outras configurações de host são lidas da configuração do aplicativo em vez da configuração do host.

URLS é uma das muitas configurações de host comuns que não é uma configuração de inicialização. Como todas as outras configurações de host que não estão na lista anterior, URLS é lida posteriormente na configuração do aplicativo. A configuração do host é um fallback para a configuração do aplicativo, portanto, a configuração do host pode ser usada para definir URLS, mas será substituída por qualquer fonte de configuração na configuração do aplicativo como appsettings.json.

Para obter mais informações, confira Alterar a raiz do conteúdo, o nome do aplicativo e o ambiente e Alterar a raiz do conteúdo, o nome do aplicativo e o ambiente por variáveis de ambiente ou linha de comando

As seções restantes neste artigo referem-se à configuração de aplicativos.

Provedores de configuração de aplicativos

O código a seguir exibe os provedores de configuração habilitados na ordem em que foram adicionados:

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

A lista anterior das fontes de configuração padrão de prioridade mais alta para a mais baixa mostra os provedores na ordem oposta em que são adicionados ao aplicativo gerado pelo modelo. Por exemplo, o provedor de configuração JSON é adicionado antes do provedor de configuração de linha de comando.

Os provedores de configuração adicionados posteriormente têm prioridade mais alta e substituem as configurações de chave anteriores. Por exemplo, se MyKey estiver configurado em appsettings.json e no ambiente, o valor do ambiente será usado. Usando os provedores de configuração padrão, o provedor de configuração de linha de comando substitui todos os outros provedores.

Para obter mais informações sobre CreateBuilder, confira Configurações do construtor padrão.

appsettings.json

Considere o seguinte arquivo appsettings.json:

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

O código a seguir do download de exemplo exibe várias das configurações 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}");
    }
}

O padrão JsonConfigurationProvider carrega a configuração na seguinte ordem:

  1. appsettings.json
  2. appsettings.{Environment}.json : por exemplo, os arquivos appsettings.Production.json e appsettings.Development.json. A versão do ambiente do arquivo é carregada com base no IHostingEnvironment.EnvironmentName. Para obter mais informações, confira Usar vários ambientes no ASP.NET Core.

Os valores de appsettings.{Environment}.json substituem as chaves em appsettings.json. Por exemplo, por padrão:

  • No desenvolvimento, a configuração de appsettings.Development.json substitui os valores encontrados em appsettings.json.
  • Na produção, a configuração de appsettings.Production.json substitui os valores encontrados em appsettings.json. Por exemplo, ao implantar o aplicativo no Azure.

Se um valor de configuração deve ser assegurado, confira GetValue. O exemplo anterior lê apenas cadeias de caracteres e não dá suporte a um valor padrão.

Usando a configuração padrão, os arquivos appsettings.json e appsettings.{Environment}.json são habilitados com reloadOnChange: true. As alterações feitas no arquivo appsettings.json e appsettings.{Environment}.jsonapós a inicialização do aplicativo são lidas pelo provedor de configuração ONJS.

Comentários no appsettings.json

Comentários em arquivos appsettings.json e appsettings.{Environment}.json são suportados usando comentários no estilo JavaScript ou C#.

Vincular dados de configuração hierárquica usando o padrão de opções

A maneira preferencial de ler os valores de configuração relacionados é usando o padrão de opções. Por exemplo, para ler os seguintes valores de configuração:

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

Crie a seguinte classe PositionOptions:

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

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

Uma classe de opções:

  • Deve ser não abstrata e com um construtor público sem parâmetros.
  • Todas as propriedades públicas de leitura e gravação do tipo são vinculadas.
  • Os campos não são vinculados. No código anterior, Position não está vinculado. O campo Position é usado para que a cadeia de caracteres "Position" não precise ser codificada no aplicativo ao associar a classe a um provedor de configuração.

O seguinte código:

  • Chama ConfigurationBinder.Bind para associar a classe PositionOptions à seção Position.
  • Exibe os dados de configuração 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}");
    }
}

No código anterior, por padrão, as alterações no arquivo de configuração JSON após a inicialização do aplicativo são lidas.

ConfigurationBinder.Get<T> associa e retorna o tipo especificado. ConfigurationBinder.Get<T> pode ser mais conveniente do que usar ConfigurationBinder.Bind. O código a seguir mostra como usar ConfigurationBinder.Get<T> com a classe PositionOptions:

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

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

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

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

No código anterior, por padrão, as alterações no arquivo de configuração JSON após a inicialização do aplicativo são lidas.

Uma abordagem alternativa ao usar o padrão de opções é associar a seção Position e adicioná-la ao contêiner do serviço de injeção de dependência. No código a seguir, PositionOptions é adicionada ao contêiner de serviço com Configure e associada à configuração:

using ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

Usando o código anterior, o código a seguir lê as opções de posição:

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

No código anterior, as alterações no arquivo de configuração JSON após a inicialização do aplicativo não são lidas. Para ler as alterações após a inicialização do aplicativo, use IOptionsSnapshot.

Usando a configuração padrão, os arquivos appsettings.json e appsettings.{Environment}.json são habilitados com reloadOnChange: true. As alterações feitas no arquivo appsettings.json e appsettings.{Environment}.jsonapós a inicialização do aplicativo são lidas pelo provedor de configuração ONJS.

Confira Provedor de configuração JSON neste documento para obter informações sobre como adicionar arquivos de configuração JSON adicionais.

Como combinar a coleção de serviços

Considere o seguinte ao registrar serviços e configurar opções:

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

Grupos de registros relacionados podem ser movidos para um método de extensão para registrar serviços. Por exemplo, os serviços de configuração são adicionados à seguinte classe:

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

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

            return services;
        }

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

            return services;
        }
    }
}

Os serviços restantes são registrados em uma classe similar. O código a seguir usa os novos métodos de extensão para registrar os serviços:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

Observação: Cada método de extensão services.Add{GROUP_NAME} adiciona e possivelmente configura serviços. Por exemplo, AddControllersWithViews adiciona os serviços que os controladores MVC com visualizações requerem e AddRazorPages adiciona os serviços que o Razor Pages requer.

Segurança e segredos do usuário

Diretrizes de dados de configuração:

  • Nunca armazene senhas ou outros dados confidenciais no código do provedor de configuração ou nos arquivos de configuração de texto sem formatação. A ferramenta Gerenciador de Segredos pode ser usada para armazenar segredos em desenvolvimento.
  • Não use segredos de produção em ambientes de teste ou de desenvolvimento.
  • Especifique segredos fora do projeto para que eles não sejam acidentalmente comprometidos com um repositório de código-fonte.

Por padrão, a fonte de configuração de segredos do usuário é registrada após as fontes de configuração JSON. Portanto, as chaves de segredos do usuário têm precedência sobre as chaves em appsettings.json e appsettings.{Environment}.json.

Para obter mais informações sobre como armazenar senhas ou outros dados confidenciais:

O Azure Key Vault armazena os segredos do aplicativo com segurança para aplicativos ASP.NET Core. Para obter mais informações, confira Provedor de configuração do Azure Key Vault no ASP.NET Core.

Variáveis de ambiente não prefixadas

Variáveis de ambiente não prefixadas são variáveis de ambiente diferentes daquelas prefixadas por ASPNETCORE_ ou DOTNET_. Por exemplo, os modelos de aplicativo Web ASP.NET Core definem "ASPNETCORE_ENVIRONMENT": "Development" em launchSettings.json. Para obter mais informações sobre variáveis de ambiente ASPNETCORE_ e DOTNET_, confira:

Usando a configuração padrão, o EnvironmentVariablesConfigurationProvider carrega a configuração dos pares chave-valor da variável de ambiente depois de ler appsettings.json, appsettings.{Environment}.json, e segredos do usuário. Portanto, os valores de chave lidos do ambiente substituem os valores lidos de appsettings.json, appsettings.{Environment}.json e segredos do usuário.

O separador : não funciona com chaves hierárquicas de variáveis de ambiente em todas as plataformas. __, o sublinhado duplo, tem:

  • Suporte em todas as plataformas. Por exemplo, o separador : não tem suporte pelo Bash, mas pelo __ tem.
  • Substituição automática por um :

Os seguintes comandos set:

  • Defina as chaves de ambiente e os valores do exemplo anterior no Windows.
  • Teste as configurações ao usar o download de exemplo. O comando dotnet run precisa ser executado no diretório do projeto.
set MyKey="My key from Environment"
set Position__Title=Environment_Editor
set Position__Name=Environment_Rick
dotnet run

As configurações de ambiente anteriores:

  • São definidas apenas em processos iniciados por meio da janela de comando em que foram definidos.
  • Não serão lidos por navegadores iniciados com o Visual Studio.

Os comandos setx a seguir podem ser usados para definir as chaves de ambiente e os valores no Windows. Diferente de set, as configurações setx são persistentes. /M define a variável no ambiente do sistema. Se o comutador /M não for usado, uma variável de ambiente do usuário será definida.

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

Para testar se os comandos anteriores substituem appsettings.json e appsettings.{Environment}.json:

  • Com o Visual Studio: saia e reinicie o Visual Studio.
  • Com a CLI: inicie uma nova janela de comando e insira dotnet run.

Chame AddEnvironmentVariables com uma cadeia de caracteres a fim de especificar um prefixo para variáveis de ambiente:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

No código anterior:

O prefixo é removido quando os pares de valores-chave de configuração são lidos.

Estes comandos testam o prefixo 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

A configuração padrão carrega variáveis de ambiente e argumentos de linha de comando prefixados com DOTNET_ e ASPNETCORE_. Os prefixos DOTNET_ e ASPNETCORE_ são usados pelo ASP.NET Core para configuração de host e aplicativo, mas não para configuração de usuário. Para obter mais informações sobre configuração de host e aplicativo, confira Host genérico do .NET.

Em Serviço de Aplicativo do Azure, selecione Nova configuração de aplicativo na página Configuração > Configurações. As configurações do aplicativo do Serviço de Aplicativo do Azure são:

  • Criptografadas em repouso e transmitidas por um canal criptografado.
  • Expostas como variáveis de ambiente.

Para saber mais, confira Aplicativos do Azure: substituir a configuração do aplicativo usando o portal do Azure.

Confira Prefixos de cadeia de conexão para obter informações sobre cadeias de conexão de banco de dados do Azure.

Nomenclatura de variáveis de ambiente

Os nomes das variáveis de ambiente refletem a estrutura de um arquivo appsettings.json. Cada elemento na hierarquia é separado por um sublinhado duplo (preferível) ou dois pontos. Quando a estrutura do elemento inclui uma matriz, o índice da matriz deve ser tratado como um nome de elemento adicional neste caminho. Considere o arquivo appsettings.json a seguir e seus valores equivalentes representados como variáveis de ambiente.

appsettings.json

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

variáveis de ambiente

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

Variáveis de ambiente definidas no launchSettings.json gerado

As variáveis de ambiente definidas em launchSettings.json substituem as definidas no ambiente do sistema. Por exemplo, os modelos da Web do ASP.NET Core geram um arquivo launchSettings.json que define a configuração do ponto de extremidade para:

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

A configuração de applicationUrl define a variável de ambiente ASPNETCORE_URLS e substitui os valores definidos no ambiente.

Variáveis de ambiente de escape no Linux

No Linux, o valor das variáveis de ambiente de URL deve ser escapado para que systemd possa analisá-lo. Use o ferramenta linux systemd-escape que suspende http:--localhost:5001

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

Exibir variáveis de ambiente

O código a seguir exibe as variáveis e valores de ambiente na inicialização do aplicativo, o que pode ser útil ao depurar as configurações do ambiente:

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

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

Linha de comando

Usando a configuração padrão, o CommandLineConfigurationProvider carrega a configuração dos pares chave-valor do argumento da linha de comando após as seguintes fontes de configuração:

  • Arquivos appsettings.json e appsettings.{Environment}.json.
  • Segredos do aplicativo no ambiente de desenvolvimento.
  • Variáveis de ambiente.

Por padrão, os valores de configuração definidos na linha de comando substituem os valores de configuração definidos com todos os outros provedores de configuração.

Argumentos de linha de comando

O comando a seguir define chaves e valores usando =:

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

O comando a seguir define chaves e valores usando /:

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

O comando a seguir define chaves e valores usando --:

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

O valor da chave:

  • Deve seguir =, ou a chave deve ter um prefixo de -- ou / quando o valor vier após um espaço.
  • Não é necessário se = for usado. Por exemplo, MySetting=.

No mesmo comando, não combine pares chave-valor do argumento de linha de comando que usam um sinal de =l com pares chave-valor que usam um espaço.

Mapeamentos de comutador

Os mapeamentos de comutador permitem fornecer a lógica de substituição do nome da chave. Forneça um dicionário de substituições de comutador para o método AddCommandLine.

Ao ser usado, o dicionário de mapeamentos de comutador é verificado para oferecer uma chave que corresponda à chave fornecida por um argumento de linha de comando. Se a chave de linha de comando for encontrada no dicionário, o valor do dicionário será passado de volta para definir o par chave-valor na configuração do aplicativo. Um mapeamento de comutador é necessário para qualquer chave de linha de comando prefixada com um traço único (-).

Regras de chave do dicionário de mapeamentos de comutador:

  • Os comutadores devem iniciar com - ou --.
  • O dicionário de mapeamentos de comutador chave não deve conter chaves duplicadas.

Para usar um dicionário de mapeamentos de comutador, passe-o para a chamada para 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();

Execute o seguinte comando para testar a substituição da chave:

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

O código a seguir mostra os valores de chave para as chaves substituídas:

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

Para aplicativos que usam mapeamentos de opção, a chamada CreateDefaultBuilder para não deve passar argumentos. A chamada AddCommandLine do método CreateDefaultBuilder não inclui opções mapeadas, e não é possível passar o dicionário de mapeamento de opções para CreateDefaultBuilder. A solução não é passar os argumentos para CreateDefaultBuilder, mas, em vez disso, permitir que o método AddCommandLine do método ConfigurationBuilder processe os dois argumentos e o dicionário de mapeamento de opções.

Definir ambiente e argumentos de linha de comando com o Visual Studio

Os argumentos de ambiente e linha de comando podem ser definidos no Visual Studio na caixa de diálogo de perfis de inicialização:

  • No Gerenciador de Soluções, clique com o botão direito do mouse no projeto e selecione Propriedades.
  • Selecione Depurar > Geral e Abrir depuração dos perfis de inicialização da IU.

Dados de configuração hierárquica

A API de configuração lê os dados de configuração hierárquica nivelando os dados hierárquicos com o uso de um delimitador nas chaves de configuração.

O download de exemplo contém o seguinte arquivo appsettings.json:

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

O código a seguir do download de exemplo exibe várias das configurações:

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

A maneira preferencial de ler dados de configuração hierárquica é usando o padrão de opções. Para obter mais informações, confira Vincular dados de configuração hierárquica neste documento.

Os métodos GetSection e GetChildren estão disponíveis para isolar as seções e os filhos de uma seção nos dados de configuração. Esses métodos serão descritos posteriormente em GetSection, GetChildren e Exists.

Teclas de configuração e valores

Teclas de configuração:

  • Não diferencia maiúsculas e minúsculas. Por exemplo, ConnectionString e connectionstring são tratados como chaves equivalentes.
  • Se uma chave e um valor forem definidos em mais de um provedor de configuração, será usado o valor do último provedor adicionado. Para obter mais informações, confira Configuração padrão.
  • Chaves hierárquicas
    • Ao interagir com a API de configuração, um separador de dois-pontos (:) funciona em todas as plataformas.
    • Nas variáveis de ambiente, talvez um separador de dois-pontos não funcione em todas as plataformas. Um sublinhado duplo, __, é compatível com todas as plataformas e é convertido automaticamente em dois-pontos :.
    • No Azure Key Vault, as chaves hierárquicas usam -- como separador. O provedor de configuração do Azure Key Vault substitui automaticamente -- por : quando os segredos são carregados na configuração do aplicativo.
  • O ConfigurationBinder dá suporte a matrizes de associação para objetos usando os índices em chaves de configuração. A associação de matriz está descrita na seção Associar uma matriz a uma classe.

Valores de configuração:

  • são cadeias de caracteres.
  • Não é possível armazenar valores nulos na configuração ou associá-los a objetos.

Provedores de configuração

A tabela a seguir mostra os provedores de configuração disponíveis para aplicativos ASP.NET Core.

Provedor Fornece a configuração de
Provedor de configuração do Azure Key Vault Cofre de Chave do Azure
Provedor de configuração do Aplicativo do Azure Configuração de Aplicativo do Azure
Provedor de configuração de linha de comando Parâmetros de linha de comando
Provedor de Configuração personalizado Fonte personalizada
Provedor de configuração de variáveis de ambiente Variáveis de ambiente
Provedor de configuração de arquivo Arquivos INI, JSON e XML
Provedor de configuração de chave por arquivo Arquivos de diretório
Provedor de configuração de memória Coleções na memória
Segredos do usuário Arquivo no diretório de perfil do usuário

As fontes de configuração são lidas na ordem especificada pelos provedores de configuração. Solicite provedores de configuração em código para atender às prioridades das fontes de configuração subjacentes exigidas pelo aplicativo.

Uma sequência comum de provedores de configuração é:

  1. appsettings.json
  2. appsettings.{Environment}.json
  3. Segredos do usuário
  4. Variáveis de ambiente usando o Provedor de configuração de variáveis de ambiente.
  5. Argumentos de linha de comando usando o Provedor de configuração de linha de comando.

Uma prática comum é adicionar o provedor de configuração de linha de comando por último em uma série de provedores, a fim de permitir que os argumentos de linha de comando substituam a configuração definida por outros provedores.

A sequência anterior de provedores é usada na configuração padrão.

Prefixos de cadeia de conexão

A API de configuração tem regras de processamento especiais para quatro variáveis de ambiente de cadeia de conexão. Essas cadeias de conexão estão envolvidas na configuração de cadeias de conexão do Azure para o ambiente do aplicativo. As variáveis de ambiente com os prefixos mostrados na tabela são carregadas no aplicativo com a configuração padrão ou quando nenhum prefixo é fornecido ao AddEnvironmentVariables.

Prefixo da cadeia de conexão Provedor
CUSTOMCONNSTR_ Provedor personalizado
MYSQLCONNSTR_ MySQL
SQLAZURECONNSTR_ Banco de Dados SQL do Azure
SQLCONNSTR_ SQL Server

Quando uma variável de ambiente for descoberta e carregada na configuração com qualquer um dos quatro prefixos mostrados na tabela:

  • A chave de configuração é criada removendo o prefixo da variável de ambiente e adicionando uma seção de chave de configuração (ConnectionStrings).
  • Um novo par chave-valor de configuração é criado para representar o provedor de conexão de banco de dados (exceto para CUSTOMCONNSTR_, que não tem um provedor indicado).
Chave de variável de ambiente Chave de configuração convertida Entrada de configuração do provedor
CUSTOMCONNSTR_{KEY} ConnectionStrings:{KEY} Entrada de configuração não criada.
MYSQLCONNSTR_{KEY} ConnectionStrings:{KEY} Chave: ConnectionStrings:{KEY}_ProviderName:
Valor: MySql.Data.MySqlClient
SQLAZURECONNSTR_{KEY} ConnectionStrings:{KEY} Chave: ConnectionStrings:{KEY}_ProviderName:
Valor: System.Data.SqlClient
SQLCONNSTR_{KEY} ConnectionStrings:{KEY} Chave: ConnectionStrings:{KEY}_ProviderName:
Valor: System.Data.SqlClient

Provedor de configuração de arquivo

FileConfigurationProvider é a classe base para carregamento da configuração do sistema de arquivos. Os seguintes provedores de configuração derivam de FileConfigurationProvider:

Provedor de configuração INI

O IniConfigurationProvider carrega a configuração de pares chave-valor do arquivo INI em runtime.

O código a seguir adiciona vários provedores de configuração:

var builder = WebApplication.CreateBuilder(args);

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

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

builder.Services.AddRazorPages();

var app = builder.Build();

No código anterior, as configurações nos arquivos MyIniConfig.ini e MyIniConfig.{Environment}.ini são substituídas pelas configurações no:

O download de exemplo contém o seguinte arquivo MyIniConfig.ini:

MyKey="MyIniConfig.ini Value"

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

[Logging:LogLevel]
Default=Information
Microsoft=Warning

O código a seguir do download de exemplo exibe várias das configurações 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}");
    }
}

Provedor de configuração JSON

O JsonConfigurationProvider carrega a configuração dos pares de valores-chave do arquivo JSON.

As sobrecargas podem especificar:

  • Se o arquivo é opcional.
  • Se a configuração será recarregada caso o arquivo seja alterado.

Considere o seguinte código:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

O código anterior:

Normalmente, você não deseja um arquivo JSON personalizado substituindo os valores definidos no provedor de configuração de variáveis de ambiente e no provedor de configuração de linha de comando.

Provedor de configuração XML

O XmlConfigurationProvider carrega a configuração de pares chave-valor do arquivo XML em runtime.

O código a seguir adiciona vários provedores de configuração:

var builder = WebApplication.CreateBuilder(args);

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

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

builder.Services.AddRazorPages();

var app = builder.Build();

No código anterior, as configurações nos arquivos MyXMLFile.xml e MyXMLFile.{Environment}.xml são substituídas pelas configurações no:

O download de exemplo contém o seguinte arquivo 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>

O código a seguir do download de exemplo exibe várias das configurações 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}");
    }
}

Elementos repetidos que usam o mesmo nome de elemento funcionarão se o atributo name for usado para diferenciar os 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>

O código a seguir lê o arquivo de configuração anterior e exibe as chaves e os 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"
                       );
    }
}

É possível usar atributos para fornecer valores:

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

O arquivo de configuração anterior carrega as seguintes chaves com value:

  • key:attribute
  • section:key:attribute

Provedor de configuração de chave por arquivo

O KeyPerFileConfigurationProvider usa arquivos do diretório como pares chave-valor de configuração. A chave é o nome do arquivo. O valor contém o conteúdo do arquivo. O provedor de configuração de chave por arquivo é usado em cenários de hospedagem do Docker.

Para ativar a configuração de chave por arquivo, chame o método de extensão AddKeyPerFile em uma instância do ConfigurationBuilder. O directoryPath para os arquivos deve ser um caminho absoluto.

As sobrecargas permitem especificar:

  • Um delegado Action<KeyPerFileConfigurationSource> que configura a origem.
  • Se o diretório é opcional, e o caminho para o diretório.

O sublinhado duplo (__) é usado como um delimitador de chave de configuração em nomes de arquivo. Por exemplo, o nome do arquivo Logging__LogLevel__System produz a chave de configuração Logging:LogLevel:System.

Chame ConfigureAppConfiguration ao criar o host para especificar a configuração do aplicativo:

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

Provedor de configuração de memória

O MemoryConfigurationProvider usa uma coleção na memória como pares chave-valor de configuração.

O código a seguir adiciona uma coleção de memória ao sistema de configuração:

var builder = WebApplication.CreateBuilder(args);

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

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

builder.Services.AddRazorPages();

var app = builder.Build();

O código a seguir do download de exemplo exibe as configurações 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}");
    }
}

No código anterior, config.AddInMemoryCollection(Dict) é adicionado após os provedores de configuração padrão. Para obter um exemplo de ordenação dos provedores de configuração, confira o provedor de configuração JSON.

Confira Associar uma matriz para outro exemplo usando MemoryConfigurationProvider.

configuração do ponto de extremidade Kestrel

configuração de ponto de extremidade específica Kestrel substitui todas as configurações de ponto de extremidade entre servidores. As configurações de ponto de extremidade entre servidores incluem:

Considere o seguinte arquivo appsettings.json usado em um aplicativo Web ASP.NET Core:

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

Quando a marcação realçada anterior é usada em um aplicativo Web ASP.NET Core e o aplicativo é iniciado na linha de comando com a seguinte configuração de ponto de extremidade entre servidores:

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

Kestrel se liga ao ponto de extremidade configurado especificamente para Kestrel no arquivo appsettings.json (https://localhost:9999) e não no https://localhost:7777.

Considere o ponto de extremidade específico Kestrel configurado como uma variável de ambiente:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

Na variável de ambiente anterior, Https é o nome do ponto de extremidade específico do Kestrel. O arquivo appsettings.json anterior também define um ponto de extremidade específico Kestrel chamado Https. Por padrão, as variáveis de ambiente que usam o provedor de configuração de variáveis de ambiente são lidas após appsettings.{Environment}.json, portanto, a variável de ambiente anterior é usada para o ponto de extremidade Https.

GetValue

ConfigurationBinder.GetValue extrai um valor de configuração com uma chave especificada e o converte para o 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}");
    }
}

No código anterior, se NumberKey não for encontrado na configuração, será usado o valor padrão 99.

GetSection, GetChildren e Exists

Para os exemplos a seguir, considere o seguinte arquivo MySubsection.json:

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

O código a seguir adiciona MySubsection.json aos provedores de configuração:

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

GetSection

IConfiguration.GetSection returna uma subseção de configuração com a chave de subseção especificada.

O código a seguir retorna valores para 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"]}'");
    }
}

O código a seguir retorna valores para 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 retorna null. Se uma seção correspondente não for encontrada, um IConfigurationSection vazio será retornado.

Quando GetSection retorna uma seção correspondente, Value não é preenchido. Key e Path são retornados quando a seção existe.

GetChildren e Exists

O código a seguir chama IConfiguration.GetChildren e retorna valores para 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);
    }
}

O código anterior chama ConfigurationExtensions.Exists para verificar se a seção existe:

Associar uma matriz

O ConfigurationBinder.Bind dá suporte a matrizes de associação para objetos usando os índices em chaves de configuração. Qualquer formato de matriz que exponha um segmento de chave numérica é capaz de associar matrizes a uma matriz de classe POCO.

Considere MyArray.json do download de exemplo:

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

O código a seguir adiciona MyArray.json aos provedores de configuração:

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

O código a seguir lê a configuração e exibe os 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; } 
}

O código anterior retorna a saída a seguir:

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

Na saída anterior, o Índice 3 tem valor value40, correspondendo a "4": "value40", no MyArray.json. Os índices de matriz vinculados são contínuos e não vinculados ao índice de chave de configuração. O associador de configuração não é capaz de vincular valores nulos ou criar entradas nulas em objetos vinculados.

Provedor de Configuração personalizado

O aplicativo de exemplo demonstra como criar um provedor de configuração básico que lê os pares chave-valor da configuração de um banco de dados usando Entity Framework (EF).

O provedor tem as seguintes características:

  • O banco de dados EF na memória é usado para fins de demonstração. Para usar um banco de dados que exija uma cadeia de conexão, implemente um ConfigurationBuilder secundário para fornecer a cadeia de conexão de outro provedor de configuração.
  • O provedor lê uma tabela de banco de dados na configuração na inicialização. O provedor não consulta o banco de dados em uma base por chave.
  • O recarregamento na alteração não está implementado, portanto, a atualização do banco de dados após a inicialização do aplicativo não tem efeito sobre a configuração do aplicativo.

Defina uma entidade EFConfigurationValue para armazenar valores de configuração no banco de dados.

Models/EFConfigurationValue.cs:

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

Adicione um EFConfigurationContext para armazenar e acessar os valores configurados.

EFConfigurationProvider/EFConfigurationContext.cs:

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

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

Crie uma classe que implementa 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);
}

Crie o provedor de configuração personalizado através da herança de ConfigurationProvider. O provedor de configuração inicializa o banco de dados quando ele está vazio. Como as chaves de configuração não diferenciam maiúsculas de minúsculas, o dicionário usado para inicializar o banco de dados é criado com o comparador que não diferencia maiúsculas de minúsculas (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;
    }
}

Um método de extensão AddEFConfiguration permite adicionar a fonte de configuração a um ConfigurationBuilder.

Extensions/EntityFrameworkExtensions.cs:

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

O código a seguir mostra como usar o EFConfigurationProvider personalizado no Program.cs :

//using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

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

var app = builder.Build();

app.Run();

Configuração de acesso com injeção de dependência (DI)

A configuração pode ser injetada em serviços usando a injeção de dependência (DI) resolvendo o serviço IConfiguration:

public class Service
{
    private readonly IConfiguration _config;

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

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

        // ...
    }
}

Para obter informações sobre como acessar valores usando IConfiguration, confira GetValue e GetSection, GetChildren e Exists neste artigo.

Acessar configuração no Razor Pages

O código a seguir exibe os dados de configuração em um Razor Page:

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

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

No código a seguir, MyOptions é adicionada ao contêiner de serviço com Configure e associada à configuração:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

A marcação a seguir usa a diretiva @injectRazor para resolver e exibir os valores de opções:

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

Acessar a configuração em um arquivo de visualização MVC

O código a seguir exibe os dados de configuração em uma visualização MVC:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

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

Acessar a configuração no Program.cs

O código a seguir acessa a configuração no arquivo Program.cs.

var builder = WebApplication.CreateBuilder(args);

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

var app = builder.Build();

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

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

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

app.Run();

No appsettings.json para o exemplo anterior:

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

Configurar opções com um delegado

As opções configuradas em um delegado substituem os valores definidos nos provedores de configuração.

No código a seguir, um serviço IConfigureOptions<TOptions> é adicionado ao contêiner de serviço. Ele usa um delegado para configurar valores para 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();

O código a seguir exibe os valores das opções:

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

No exemplo anterior, os valores de Option1 e Option2 são especificados em appsettings.json e substituídos pelo delegado configurado.

Configuração do host versus do aplicativo

Antes do aplicativo ser configurado e iniciado, um host é configurado e iniciado. O host é responsável pelo gerenciamento de tempo de vida e pela inicialização do aplicativo. O aplicativo e o host são configurados usando os provedores de configuração descritos neste tópico. Os pares chave-valor de configuração do host também estão incluídos na configuração do aplicativo. Para obter mais informações sobre como os provedores de configuração são usados quando o host é compilado e como as fontes de configuração afetam a configuração do host, confira Visão geral dos fundamentos do ASP.NET Core.

Configuração de host padrão

Para obter detalhes sobre a configuração padrão ao usar o host da Web, confira a versão do ASP.NET Core 2.2 deste tópico.

  • A configuração do host é fornecida de:
  • A configuração padrão do host da Web foi estabelecida (ConfigureWebHostDefaults):
    • O Kestrel é usado como o servidor Web e configurado usando provedores de configuração do aplicativo.
    • Adicione o middleware de filtragem de host.
    • Adicione o middleware de cabeçalhos encaminhados se a variável de ambiente ASPNETCORE_FORWARDEDHEADERS_ENABLED for definida para true.
    • Habilite a integração de IIS.

Outra configuração

Este tópico refere-se apenas à configuração do aplicativo. Outros aspectos da execução e hospedagem de aplicativos ASP.NET Core são configurados usando arquivos de configuração não abordados neste tópico:

As variáveis de ambiente definidas em launchSettings.json substituem as definidas no ambiente do sistema.

Para saber mais sobre como migrar a configuração do aplicativo de versões anteriores do ASP.NET, confira Atualizar do ASP.NET para o ASP.NET Core.

Adicionar configuração de um assembly externo

Uma implementação IHostingStartup permite adicionar melhorias a um aplicativo durante a inicialização de um assembly externo fora da classe Startup do aplicativo. Para obter mais informações, confira Usar assemblies de inicialização de hospedagem no ASP.NET Core.

Recursos adicionais

A configuração de aplicativos no ASP.NET Core é realizada usando um ou mais provedores de configuração. Os provedores de configuração leem os dados de configuração de pares chave-valor usando uma variedade de fontes de configuração:

  • Arquivos de configurações, como appsettings.json
  • Variáveis de ambiente
  • Azure Key Vault
  • Configuração de Aplicativos do Azure
  • Argumentos de linha de comando
  • Provedores personalizados, instalados ou criados
  • Arquivos de diretório
  • Objetos do .NET na memória

Este artigo fornece informações sobre configuração no ASP.NET Core. Para obter informações sobre como usar a configuração em aplicativos de console, confira Configuração do .NET.

Configuração de aplicativos e hosts

Aplicativos ASP.NET Core configuram e inicializam um host. O host é responsável pelo gerenciamento de tempo de vida e pela inicialização do aplicativo. Os modelos ASP.NET Core criam um WebApplicationBuilder que contém o host. Embora algumas configurações possam ser feitas tanto no host quanto nos provedores de configuração de aplicativos, em geral, apenas a configuração necessária para o host deve ser feita na configuração do host.

A configuração de aplicativos é a prioridade mais alta e é detalhada na próxima seção. A configuração de hosts segue a configuração de aplicativos e é descrita neste artigo.

Fontes de configuração de aplicativos padrão

Os aplicativos Web ASP.NET Core criados com dotnet new ou Visual Studio geram o seguinte código:

var builder = WebApplication.CreateBuilder(args);

O WebApplication.CreateBuilder inicializa uma nova instância da classe WebApplicationBuilder com os padrões pré-configurados. O WebApplicationBuilder (builder) inicializado fornece a configuração padrão para o aplicativo na seguinte ordem, da prioridade mais alta para a mais baixa:

  1. Argumentos de linha de comando usando o Provedor de configuração de linha de comando.
  2. Variáveis de ambiente não prefixadas usando o provedor de configuração de variáveis de ambiente não prefixadas.
  3. Segredos do usuário quando o aplicativo é executado no ambiente Development.
  4. appsettings.{Environment}.json usando o provedor de configuração JSON. Por exemplo, appsettings.Production.json e appsettings.Development.json.
  5. appsettings.json usando o provedor de configuração JSON.
  6. Um fallback para a configuração do host descrita na próxima seção.

Fontes de configuração de host padrão

A lista a seguir contém as fontes de configuração de host padrão da prioridade mais alta para a mais baixa:

  1. Variáveis ​​de ambiente prefixadas pelo ASPNETCORE_ usando o provedor de configuração de variáveis ​​de ambiente.
  2. Argumentos de linha de comando usando o provedor de configuração de linha de comando
  3. Variáveis ​​de ambiente prefixadas pelo DOTNET_ usando o provedor de configuração de variáveis ​​de ambiente.

Quando um valor de configuração é definido na configuração do host e do aplicativo, a configuração do aplicativo é usada.

Confira Explicação neste comentário do GitHub para obter uma explicação de por que, na configuração do host, as variáveis ​​de ambiente prefixadas ASPNETCORE_ têm prioridade mais alta do que os argumentos de linha de comando.

Variáveis do host

As seguintes variáveis são bloqueadas antecipadamente ao inicializar os construtores de host e não podem ser influenciadas pela configuração do aplicativo:

Todas as outras configurações de host são lidas da configuração do aplicativo em vez da configuração do host.

URLS é uma das muitas configurações de host comuns que não é uma configuração de inicialização. Como todas as outras configurações de host que não estão na lista anterior, URLS é lida posteriormente na configuração do aplicativo. A configuração do host é um fallback para a configuração do aplicativo, portanto, a configuração do host pode ser usada para definir URLS, mas será substituída por qualquer fonte de configuração na configuração do aplicativo como appsettings.json.

Para obter mais informações, confira Alterar a raiz do conteúdo, o nome do aplicativo e o ambiente e Alterar a raiz do conteúdo, o nome do aplicativo e o ambiente por variáveis de ambiente ou linha de comando

As seções restantes neste artigo referem-se à configuração de aplicativos.

Provedores de configuração de aplicativos

O código a seguir exibe os provedores de configuração habilitados na ordem em que foram adicionados:

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

A lista anterior das fontes de configuração padrão de prioridade mais alta para a mais baixa mostra os provedores na ordem oposta em que são adicionados ao aplicativo gerado pelo modelo. Por exemplo, o provedor de configuração JSON é adicionado antes do provedor de configuração de linha de comando.

Os provedores de configuração adicionados posteriormente têm prioridade mais alta e substituem as configurações de chave anteriores. Por exemplo, se MyKey estiver configurado em appsettings.json e no ambiente, o valor do ambiente será usado. Usando os provedores de configuração padrão, o provedor de configuração de linha de comando substitui todos os outros provedores.

Para obter mais informações sobre CreateBuilder, confira Configurações do construtor padrão.

appsettings.json

Considere o seguinte arquivo appsettings.json:

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

O código a seguir do download de exemplo exibe várias das configurações 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}");
    }
}

O padrão JsonConfigurationProvider carrega a configuração na seguinte ordem:

  1. appsettings.json
  2. appsettings.{Environment}.json : por exemplo, os arquivos appsettings.Production.json e appsettings.Development.json. A versão do ambiente do arquivo é carregada com base no IHostingEnvironment.EnvironmentName. Para obter mais informações, confira Usar vários ambientes no ASP.NET Core.

Os valores de appsettings.{Environment}.json substituem as chaves em appsettings.json. Por exemplo, por padrão:

  • No desenvolvimento, a configuração de appsettings.Development.json substitui os valores encontrados em appsettings.json.
  • Na produção, a configuração de appsettings.Production.json substitui os valores encontrados em appsettings.json. Por exemplo, ao implantar o aplicativo no Azure.

Se um valor de configuração deve ser assegurado, confira GetValue. O exemplo anterior lê apenas cadeias de caracteres e não dá suporte a um valor padrão.

Usando a configuração padrão, os arquivos appsettings.json e appsettings.{Environment}.json são habilitados com reloadOnChange: true. As alterações feitas no arquivo appsettings.json e appsettings.{Environment}.jsonapós a inicialização do aplicativo são lidas pelo provedor de configuração ONJS.

Vincular dados de configuração hierárquica usando o padrão de opções

A maneira preferencial de ler os valores de configuração relacionados é usando o padrão de opções. Por exemplo, para ler os seguintes valores de configuração:

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

Crie a seguinte classe PositionOptions:

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

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

Uma classe de opções:

  • Deve ser não abstrata e com um construtor público sem parâmetros.
  • Todas as propriedades públicas de leitura e gravação do tipo são vinculadas.
  • Os campos não são vinculados. No código anterior, Position não está vinculado. O campo Position é usado para que a cadeia de caracteres "Position" não precise ser codificada no aplicativo ao associar a classe a um provedor de configuração.

O seguinte código:

  • Chama ConfigurationBinder.Bind para associar a classe PositionOptions à seção Position.
  • Exibe os dados de configuração 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}");
    }
}

No código anterior, por padrão, as alterações no arquivo de configuração JSON após a inicialização do aplicativo são lidas.

ConfigurationBinder.Get<T> associa e retorna o tipo especificado. ConfigurationBinder.Get<T> pode ser mais conveniente do que usar ConfigurationBinder.Bind. O código a seguir mostra como usar ConfigurationBinder.Get<T> com a classe PositionOptions:

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

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

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

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

No código anterior, por padrão, as alterações no arquivo de configuração JSON após a inicialização do aplicativo são lidas.

Uma abordagem alternativa ao usar o padrão de opções é associar a seção Position e adicioná-la ao contêiner do serviço de injeção de dependência. No código a seguir, PositionOptions é adicionada ao contêiner de serviço com Configure e associada à configuração:

using ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

Usando o código anterior, o código a seguir lê as opções de posição:

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

No código anterior, as alterações no arquivo de configuração JSON após a inicialização do aplicativo não são lidas. Para ler as alterações após a inicialização do aplicativo, use IOptionsSnapshot.

Usando a configuração padrão, os arquivos appsettings.json e appsettings.{Environment}.json são habilitados com reloadOnChange: true. As alterações feitas no arquivo appsettings.json e appsettings.{Environment}.jsonapós a inicialização do aplicativo são lidas pelo provedor de configuração ONJS.

Confira Provedor de configuração JSON neste documento para obter informações sobre como adicionar arquivos de configuração JSON adicionais.

Como combinar a coleção de serviços

Considere o seguinte ao registrar serviços e configurar opções:

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

Grupos de registros relacionados podem ser movidos para um método de extensão para registrar serviços. Por exemplo, os serviços de configuração são adicionados à seguinte classe:

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

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

            return services;
        }

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

            return services;
        }
    }
}

Os serviços restantes são registrados em uma classe similar. O código a seguir usa os novos métodos de extensão para registrar os serviços:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

Observação: Cada método de extensão services.Add{GROUP_NAME} adiciona e possivelmente configura serviços. Por exemplo, AddControllersWithViews adiciona os serviços que os controladores MVC com visualizações requerem e AddRazorPages adiciona os serviços que o Razor Pages requer.

Segurança e segredos do usuário

Diretrizes de dados de configuração:

  • Nunca armazene senhas ou outros dados confidenciais no código do provedor de configuração ou nos arquivos de configuração de texto sem formatação. A ferramenta Gerenciador de Segredos pode ser usada para armazenar segredos em desenvolvimento.
  • Não use segredos de produção em ambientes de teste ou de desenvolvimento.
  • Especifique segredos fora do projeto para que eles não sejam acidentalmente comprometidos com um repositório de código-fonte.

Por padrão, a fonte de configuração de segredos do usuário é registrada após as fontes de configuração JSON. Portanto, as chaves de segredos do usuário têm precedência sobre as chaves em appsettings.json e appsettings.{Environment}.json.

Para obter mais informações sobre como armazenar senhas ou outros dados confidenciais:

O Azure Key Vault armazena os segredos do aplicativo com segurança para aplicativos ASP.NET Core. Para obter mais informações, confira Provedor de configuração do Azure Key Vault no ASP.NET Core.

Variáveis de ambiente não prefixadas

Variáveis de ambiente não prefixadas são variáveis de ambiente diferentes daquelas prefixadas por ASPNETCORE_ ou DOTNET_. Por exemplo, os modelos de aplicativo Web ASP.NET Core definem "ASPNETCORE_ENVIRONMENT": "Development" em launchSettings.json. Para obter mais informações sobre variáveis de ambiente ASPNETCORE_ e DOTNET_, confira:

Usando a configuração padrão, o EnvironmentVariablesConfigurationProvider carrega a configuração dos pares chave-valor da variável de ambiente depois de ler appsettings.json, appsettings.{Environment}.json, e segredos do usuário. Portanto, os valores de chave lidos do ambiente substituem os valores lidos de appsettings.json, appsettings.{Environment}.json e segredos do usuário.

O separador : não funciona com chaves hierárquicas de variáveis de ambiente em todas as plataformas. __, o sublinhado duplo, tem:

  • Suporte em todas as plataformas. Por exemplo, o separador : não tem suporte pelo Bash, mas pelo __ tem.
  • Substituição automática por um :

Os seguintes comandos set:

  • Defina as chaves de ambiente e os valores do exemplo anterior no Windows.
  • Teste as configurações ao usar o download de exemplo. O comando dotnet run precisa ser executado no diretório do projeto.
set MyKey="My key from Environment"
set Position__Title=Environment_Editor
set Position__Name=Environment_Rick
dotnet run

As configurações de ambiente anteriores:

  • São definidas apenas em processos iniciados por meio da janela de comando em que foram definidos.
  • Não serão lidos por navegadores iniciados com o Visual Studio.

Os comandos setx a seguir podem ser usados para definir as chaves de ambiente e os valores no Windows. Diferente de set, as configurações setx são persistentes. /M define a variável no ambiente do sistema. Se o comutador /M não for usado, uma variável de ambiente do usuário será definida.

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

Para testar se os comandos anteriores substituem appsettings.json e appsettings.{Environment}.json:

  • Com o Visual Studio: saia e reinicie o Visual Studio.
  • Com a CLI: inicie uma nova janela de comando e insira dotnet run.

Chame AddEnvironmentVariables com uma cadeia de caracteres a fim de especificar um prefixo para variáveis de ambiente:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

No código anterior:

O prefixo é removido quando os pares de valores-chave de configuração são lidos.

Estes comandos testam o prefixo 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

A configuração padrão carrega variáveis de ambiente e argumentos de linha de comando prefixados com DOTNET_ e ASPNETCORE_. Os prefixos DOTNET_ e ASPNETCORE_ são usados pelo ASP.NET Core para configuração de host e aplicativo, mas não para configuração de usuário. Para obter mais informações sobre configuração de host e aplicativo, confira Host genérico do .NET.

Em Serviço de Aplicativo do Azure, selecione Nova configuração de aplicativo na página Configuração > Configurações. As configurações do aplicativo do Serviço de Aplicativo do Azure são:

  • Criptografadas em repouso e transmitidas por um canal criptografado.
  • Expostas como variáveis de ambiente.

Para saber mais, confira Aplicativos do Azure: substituir a configuração do aplicativo usando o portal do Azure.

Confira Prefixos de cadeia de conexão para obter informações sobre cadeias de conexão de banco de dados do Azure.

Nomenclatura de variáveis de ambiente

Os nomes das variáveis de ambiente refletem a estrutura de um arquivo appsettings.json. Cada elemento na hierarquia é separado por um sublinhado duplo (preferível) ou dois pontos. Quando a estrutura do elemento inclui uma matriz, o índice da matriz deve ser tratado como um nome de elemento adicional neste caminho. Considere o arquivo appsettings.json a seguir e seus valores equivalentes representados como variáveis de ambiente.

appsettings.json

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

variáveis de ambiente

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

Variáveis de ambiente definidas no launchSettings.json gerado

As variáveis de ambiente definidas em launchSettings.json substituem as definidas no ambiente do sistema. Por exemplo, os modelos da Web do ASP.NET Core geram um arquivo launchSettings.json que define a configuração do ponto de extremidade para:

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

A configuração de applicationUrl define a variável de ambiente ASPNETCORE_URLS e substitui os valores definidos no ambiente.

Variáveis de ambiente de escape no Linux

No Linux, o valor das variáveis de ambiente de URL deve ser escapado para que systemd possa analisá-lo. Use o ferramenta linux systemd-escape que suspende http:--localhost:5001

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

Exibir variáveis de ambiente

O código a seguir exibe as variáveis e valores de ambiente na inicialização do aplicativo, o que pode ser útil ao depurar as configurações do ambiente:

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

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

Linha de comando

Usando a configuração padrão, o CommandLineConfigurationProvider carrega a configuração dos pares chave-valor do argumento da linha de comando após as seguintes fontes de configuração:

  • Arquivos appsettings.json e appsettings.{Environment}.json.
  • Segredos do aplicativo no ambiente de desenvolvimento.
  • Variáveis de ambiente.

Por padrão, os valores de configuração definidos na linha de comando substituem os valores de configuração definidos com todos os outros provedores de configuração.

Argumentos de linha de comando

O comando a seguir define chaves e valores usando =:

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

O comando a seguir define chaves e valores usando /:

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

O comando a seguir define chaves e valores usando --:

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

O valor da chave:

  • Deve seguir =, ou a chave deve ter um prefixo de -- ou / quando o valor vier após um espaço.
  • Não é necessário se = for usado. Por exemplo, MySetting=.

No mesmo comando, não combine pares chave-valor do argumento de linha de comando que usam um sinal de =l com pares chave-valor que usam um espaço.

Mapeamentos de comutador

Os mapeamentos de comutador permitem fornecer a lógica de substituição do nome da chave. Forneça um dicionário de substituições de comutador para o método AddCommandLine.

Ao ser usado, o dicionário de mapeamentos de comutador é verificado para oferecer uma chave que corresponda à chave fornecida por um argumento de linha de comando. Se a chave de linha de comando for encontrada no dicionário, o valor do dicionário será passado de volta para definir o par chave-valor na configuração do aplicativo. Um mapeamento de comutador é necessário para qualquer chave de linha de comando prefixada com um traço único (-).

Regras de chave do dicionário de mapeamentos de comutador:

  • Os comutadores devem iniciar com - ou --.
  • O dicionário de mapeamentos de comutador chave não deve conter chaves duplicadas.

Para usar um dicionário de mapeamentos de comutador, passe-o para a chamada para 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();

Execute o seguinte comando para testar a substituição da chave:

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

O código a seguir mostra os valores de chave para as chaves substituídas:

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

Para aplicativos que usam mapeamentos de opção, a chamada CreateDefaultBuilder para não deve passar argumentos. A chamada AddCommandLine do método CreateDefaultBuilder não inclui opções mapeadas, e não é possível passar o dicionário de mapeamento de opções para CreateDefaultBuilder. A solução não é passar os argumentos para CreateDefaultBuilder, mas, em vez disso, permitir que o método AddCommandLine do método ConfigurationBuilder processe os dois argumentos e o dicionário de mapeamento de opções.

Definir ambiente e argumentos de linha de comando com o Visual Studio

Os argumentos de ambiente e linha de comando podem ser definidos no Visual Studio na caixa de diálogo de perfis de inicialização:

  • No Gerenciador de Soluções, clique com o botão direito do mouse no projeto e selecione Propriedades.
  • Selecione Depurar > Geral e Abrir depuração dos perfis de inicialização da IU.

Dados de configuração hierárquica

A API de configuração lê os dados de configuração hierárquica nivelando os dados hierárquicos com o uso de um delimitador nas chaves de configuração.

O download de exemplo contém o seguinte arquivo appsettings.json:

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

O código a seguir do download de exemplo exibe várias das configurações:

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

A maneira preferencial de ler dados de configuração hierárquica é usando o padrão de opções. Para obter mais informações, confira Vincular dados de configuração hierárquica neste documento.

Os métodos GetSection e GetChildren estão disponíveis para isolar as seções e os filhos de uma seção nos dados de configuração. Esses métodos serão descritos posteriormente em GetSection, GetChildren e Exists.

Teclas de configuração e valores

Teclas de configuração:

  • Não diferencia maiúsculas e minúsculas. Por exemplo, ConnectionString e connectionstring são tratados como chaves equivalentes.
  • Se uma chave e um valor forem definidos em mais de um provedor de configuração, será usado o valor do último provedor adicionado. Para obter mais informações, confira Configuração padrão.
  • Chaves hierárquicas
    • Ao interagir com a API de configuração, um separador de dois-pontos (:) funciona em todas as plataformas.
    • Nas variáveis de ambiente, talvez um separador de dois-pontos não funcione em todas as plataformas. Um sublinhado duplo, __, é compatível com todas as plataformas e é convertido automaticamente em dois-pontos :.
    • No Azure Key Vault, as chaves hierárquicas usam -- como separador. O provedor de configuração do Azure Key Vault substitui automaticamente -- por : quando os segredos são carregados na configuração do aplicativo.
  • O ConfigurationBinder dá suporte a matrizes de associação para objetos usando os índices em chaves de configuração. A associação de matriz está descrita na seção Associar uma matriz a uma classe.

Valores de configuração:

  • são cadeias de caracteres.
  • Não é possível armazenar valores nulos na configuração ou associá-los a objetos.

Provedores de configuração

A tabela a seguir mostra os provedores de configuração disponíveis para aplicativos ASP.NET Core.

Provedor Fornece a configuração de
Provedor de configuração do Azure Key Vault Cofre de Chave do Azure
Provedor de configuração do Aplicativo do Azure Configuração de Aplicativo do Azure
Provedor de configuração de linha de comando Parâmetros de linha de comando
Provedor de Configuração personalizado Fonte personalizada
Provedor de configuração de variáveis de ambiente Variáveis de ambiente
Provedor de configuração de arquivo Arquivos INI, JSON e XML
Provedor de configuração de chave por arquivo Arquivos de diretório
Provedor de configuração de memória Coleções na memória
Segredos do usuário Arquivo no diretório de perfil do usuário

As fontes de configuração são lidas na ordem especificada pelos provedores de configuração. Solicite provedores de configuração em código para atender às prioridades das fontes de configuração subjacentes exigidas pelo aplicativo.

Uma sequência comum de provedores de configuração é:

  1. appsettings.json
  2. appsettings.{Environment}.json
  3. Segredos do usuário
  4. Variáveis de ambiente usando o Provedor de configuração de variáveis de ambiente.
  5. Argumentos de linha de comando usando o Provedor de configuração de linha de comando.

Uma prática comum é adicionar o provedor de configuração de linha de comando por último em uma série de provedores, a fim de permitir que os argumentos de linha de comando substituam a configuração definida por outros provedores.

A sequência anterior de provedores é usada na configuração padrão.

Prefixos de cadeia de conexão

A API de configuração tem regras de processamento especiais para quatro variáveis de ambiente de cadeia de conexão. Essas cadeias de conexão estão envolvidas na configuração de cadeias de conexão do Azure para o ambiente do aplicativo. As variáveis de ambiente com os prefixos mostrados na tabela são carregadas no aplicativo com a configuração padrão ou quando nenhum prefixo é fornecido ao AddEnvironmentVariables.

Prefixo da cadeia de conexão Provedor
CUSTOMCONNSTR_ Provedor personalizado
MYSQLCONNSTR_ MySQL
SQLAZURECONNSTR_ Banco de Dados SQL do Azure
SQLCONNSTR_ SQL Server

Quando uma variável de ambiente for descoberta e carregada na configuração com qualquer um dos quatro prefixos mostrados na tabela:

  • A chave de configuração é criada removendo o prefixo da variável de ambiente e adicionando uma seção de chave de configuração (ConnectionStrings).
  • Um novo par chave-valor de configuração é criado para representar o provedor de conexão de banco de dados (exceto para CUSTOMCONNSTR_, que não tem um provedor indicado).
Chave de variável de ambiente Chave de configuração convertida Entrada de configuração do provedor
CUSTOMCONNSTR_{KEY} ConnectionStrings:{KEY} Entrada de configuração não criada.
MYSQLCONNSTR_{KEY} ConnectionStrings:{KEY} Chave: ConnectionStrings:{KEY}_ProviderName:
Valor: MySql.Data.MySqlClient
SQLAZURECONNSTR_{KEY} ConnectionStrings:{KEY} Chave: ConnectionStrings:{KEY}_ProviderName:
Valor: System.Data.SqlClient
SQLCONNSTR_{KEY} ConnectionStrings:{KEY} Chave: ConnectionStrings:{KEY}_ProviderName:
Valor: System.Data.SqlClient

Provedor de configuração de arquivo

FileConfigurationProvider é a classe base para carregamento da configuração do sistema de arquivos. Os seguintes provedores de configuração derivam de FileConfigurationProvider:

Provedor de configuração INI

O IniConfigurationProvider carrega a configuração de pares chave-valor do arquivo INI em runtime.

O código a seguir adiciona vários provedores de configuração:

var builder = WebApplication.CreateBuilder(args);

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

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

builder.Services.AddRazorPages();

var app = builder.Build();

No código anterior, as configurações nos arquivos MyIniConfig.ini e MyIniConfig.{Environment}.ini são substituídas pelas configurações no:

O download de exemplo contém o seguinte arquivo MyIniConfig.ini:

MyKey="MyIniConfig.ini Value"

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

[Logging:LogLevel]
Default=Information
Microsoft=Warning

O código a seguir do download de exemplo exibe várias das configurações 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}");
    }
}

Provedor de configuração JSON

O JsonConfigurationProvider carrega a configuração dos pares de valores-chave do arquivo JSON.

As sobrecargas podem especificar:

  • Se o arquivo é opcional.
  • Se a configuração será recarregada caso o arquivo seja alterado.

Considere o seguinte código:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

O código anterior:

Normalmente, você não deseja um arquivo JSON personalizado substituindo os valores definidos no provedor de configuração de variáveis de ambiente e no provedor de configuração de linha de comando.

Provedor de configuração XML

O XmlConfigurationProvider carrega a configuração de pares chave-valor do arquivo XML em runtime.

O código a seguir adiciona vários provedores de configuração:

var builder = WebApplication.CreateBuilder(args);

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

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

builder.Services.AddRazorPages();

var app = builder.Build();

No código anterior, as configurações nos arquivos MyXMLFile.xml e MyXMLFile.{Environment}.xml são substituídas pelas configurações no:

O download de exemplo contém o seguinte arquivo 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>

O código a seguir do download de exemplo exibe várias das configurações 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}");
    }
}

Elementos repetidos que usam o mesmo nome de elemento funcionarão se o atributo name for usado para diferenciar os 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>

O código a seguir lê o arquivo de configuração anterior e exibe as chaves e os 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"
                       );
    }
}

É possível usar atributos para fornecer valores:

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

O arquivo de configuração anterior carrega as seguintes chaves com value:

  • key:attribute
  • section:key:attribute

Provedor de configuração de chave por arquivo

O KeyPerFileConfigurationProvider usa arquivos do diretório como pares chave-valor de configuração. A chave é o nome do arquivo. O valor contém o conteúdo do arquivo. O provedor de configuração de chave por arquivo é usado em cenários de hospedagem do Docker.

Para ativar a configuração de chave por arquivo, chame o método de extensão AddKeyPerFile em uma instância do ConfigurationBuilder. O directoryPath para os arquivos deve ser um caminho absoluto.

As sobrecargas permitem especificar:

  • Um delegado Action<KeyPerFileConfigurationSource> que configura a origem.
  • Se o diretório é opcional, e o caminho para o diretório.

O sublinhado duplo (__) é usado como um delimitador de chave de configuração em nomes de arquivo. Por exemplo, o nome do arquivo Logging__LogLevel__System produz a chave de configuração Logging:LogLevel:System.

Chame ConfigureAppConfiguration ao criar o host para especificar a configuração do aplicativo:

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

Provedor de configuração de memória

O MemoryConfigurationProvider usa uma coleção na memória como pares chave-valor de configuração.

O código a seguir adiciona uma coleção de memória ao sistema de configuração:

var builder = WebApplication.CreateBuilder(args);

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

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

builder.Services.AddRazorPages();

var app = builder.Build();

O código a seguir do download de exemplo exibe as configurações 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}");
    }
}

No código anterior, config.AddInMemoryCollection(Dict) é adicionado após os provedores de configuração padrão. Para obter um exemplo de ordenação dos provedores de configuração, confira o provedor de configuração JSON.

Confira Associar uma matriz para outro exemplo usando MemoryConfigurationProvider.

configuração do ponto de extremidade Kestrel

configuração de ponto de extremidade específica Kestrel substitui todas as configurações de ponto de extremidade entre servidores. As configurações de ponto de extremidade entre servidores incluem:

Considere o seguinte arquivo appsettings.json usado em um aplicativo Web ASP.NET Core:

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

Quando a marcação realçada anterior é usada em um aplicativo Web ASP.NET Core e o aplicativo é iniciado na linha de comando com a seguinte configuração de ponto de extremidade entre servidores:

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

Kestrel se liga ao ponto de extremidade configurado especificamente para Kestrel no arquivo appsettings.json (https://localhost:9999) e não no https://localhost:7777.

Considere o ponto de extremidade específico Kestrel configurado como uma variável de ambiente:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

Na variável de ambiente anterior, Https é o nome do ponto de extremidade específico do Kestrel. O arquivo appsettings.json anterior também define um ponto de extremidade específico Kestrel chamado Https. Por padrão, as variáveis de ambiente que usam o provedor de configuração de variáveis de ambiente são lidas após appsettings.{Environment}.json, portanto, a variável de ambiente anterior é usada para o ponto de extremidade Https.

GetValue

ConfigurationBinder.GetValue extrai um valor de configuração com uma chave especificada e o converte para o 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}");
    }
}

No código anterior, se NumberKey não for encontrado na configuração, será usado o valor padrão 99.

GetSection, GetChildren e Exists

Para os exemplos a seguir, considere o seguinte arquivo MySubsection.json:

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

O código a seguir adiciona MySubsection.json aos provedores de configuração:

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

GetSection

IConfiguration.GetSection returna uma subseção de configuração com a chave de subseção especificada.

O código a seguir retorna valores para 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"]}'");
    }
}

O código a seguir retorna valores para 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 retorna null. Se uma seção correspondente não for encontrada, um IConfigurationSection vazio será retornado.

Quando GetSection retorna uma seção correspondente, Value não é preenchido. Key e Path são retornados quando a seção existe.

GetChildren e Exists

O código a seguir chama IConfiguration.GetChildren e retorna valores para 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);
    }
}

O código anterior chama ConfigurationExtensions.Exists para verificar se a seção existe:

Associar uma matriz

O ConfigurationBinder.Bind dá suporte a matrizes de associação para objetos usando os índices em chaves de configuração. Qualquer formato de matriz que exponha um segmento de chave numérica é capaz de associar matrizes a uma matriz de classe POCO.

Considere MyArray.json do download de exemplo:

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

O código a seguir adiciona MyArray.json aos provedores de configuração:

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRazorPages();

var app = builder.Build();

O código a seguir lê a configuração e exibe os 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; } 
}

O código anterior retorna a saída a seguir:

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

Na saída anterior, o Índice 3 tem valor value40, correspondendo a "4": "value40", no MyArray.json. Os índices de matriz vinculados são contínuos e não vinculados ao índice de chave de configuração. O associador de configuração não é capaz de vincular valores nulos ou criar entradas nulas em objetos vinculados.

Provedor de Configuração personalizado

O aplicativo de exemplo demonstra como criar um provedor de configuração básico que lê os pares chave-valor da configuração de um banco de dados usando Entity Framework (EF).

O provedor tem as seguintes características:

  • O banco de dados EF na memória é usado para fins de demonstração. Para usar um banco de dados que exija uma cadeia de conexão, implemente um ConfigurationBuilder secundário para fornecer a cadeia de conexão de outro provedor de configuração.
  • O provedor lê uma tabela de banco de dados na configuração na inicialização. O provedor não consulta o banco de dados em uma base por chave.
  • O recarregamento na alteração não está implementado, portanto, a atualização do banco de dados após a inicialização do aplicativo não tem efeito sobre a configuração do aplicativo.

Defina uma entidade EFConfigurationValue para armazenar valores de configuração no banco de dados.

Models/EFConfigurationValue.cs:

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

Adicione um EFConfigurationContext para armazenar e acessar os valores configurados.

EFConfigurationProvider/EFConfigurationContext.cs:

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

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

Crie uma classe que implementa 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);
}

Crie o provedor de configuração personalizado através da herança de ConfigurationProvider. O provedor de configuração inicializa o banco de dados quando ele está vazio. Como as chaves de configuração não diferenciam maiúsculas de minúsculas, o dicionário usado para inicializar o banco de dados é criado com o comparador que não diferencia maiúsculas de minúsculas (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;
    }
}

Um método de extensão AddEFConfiguration permite adicionar a fonte de configuração a um ConfigurationBuilder.

Extensions/EntityFrameworkExtensions.cs:

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

O código a seguir mostra como usar o EFConfigurationProvider personalizado no Program.cs :

//using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

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

var app = builder.Build();

app.Run();

Configuração de acesso com injeção de dependência (DI)

A configuração pode ser injetada em serviços usando a injeção de dependência (DI) resolvendo o serviço IConfiguration:

public class Service
{
    private readonly IConfiguration _config;

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

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

        // ...
    }
}

Para obter informações sobre como acessar valores usando IConfiguration, confira GetValue e GetSection, GetChildren e Exists neste artigo.

Acessar configuração no Razor Pages

O código a seguir exibe os dados de configuração em um Razor Page:

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

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

No código a seguir, MyOptions é adicionada ao contêiner de serviço com Configure e associada à configuração:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

var app = builder.Build();

A marcação a seguir usa a diretiva @injectRazor para resolver e exibir os valores de opções:

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

Acessar a configuração em um arquivo de visualização MVC

O código a seguir exibe os dados de configuração em uma visualização MVC:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

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

Acessar a configuração no Program.cs

O código a seguir acessa a configuração no arquivo Program.cs.

var builder = WebApplication.CreateBuilder(args);

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

var app = builder.Build();

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

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

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

app.Run();

No appsettings.json para o exemplo anterior:

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

Configurar opções com um delegado

As opções configuradas em um delegado substituem os valores definidos nos provedores de configuração.

No código a seguir, um serviço IConfigureOptions<TOptions> é adicionado ao contêiner de serviço. Ele usa um delegado para configurar valores para 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();

O código a seguir exibe os valores das opções:

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

No exemplo anterior, os valores de Option1 e Option2 são especificados em appsettings.json e substituídos pelo delegado configurado.

Configuração do host versus do aplicativo

Antes do aplicativo ser configurado e iniciado, um host é configurado e iniciado. O host é responsável pelo gerenciamento de tempo de vida e pela inicialização do aplicativo. O aplicativo e o host são configurados usando os provedores de configuração descritos neste tópico. Os pares chave-valor de configuração do host também estão incluídos na configuração do aplicativo. Para obter mais informações sobre como os provedores de configuração são usados quando o host é compilado e como as fontes de configuração afetam a configuração do host, confira Visão geral dos fundamentos do ASP.NET Core.

Configuração de host padrão

Para obter detalhes sobre a configuração padrão ao usar o host da Web, confira a versão do ASP.NET Core 2.2 deste tópico.

  • A configuração do host é fornecida de:
  • A configuração padrão do host da Web foi estabelecida (ConfigureWebHostDefaults):
    • O Kestrel é usado como o servidor Web e configurado usando provedores de configuração do aplicativo.
    • Adicione o middleware de filtragem de host.
    • Adicione o middleware de cabeçalhos encaminhados se a variável de ambiente ASPNETCORE_FORWARDEDHEADERS_ENABLED for definida para true.
    • Habilite a integração de IIS.

Outra configuração

Este tópico refere-se apenas à configuração do aplicativo. Outros aspectos da execução e hospedagem de aplicativos ASP.NET Core são configurados usando arquivos de configuração não abordados neste tópico:

As variáveis de ambiente definidas em launchSettings.json substituem as definidas no ambiente do sistema.

Para saber mais sobre como migrar a configuração do aplicativo de versões anteriores do ASP.NET, confira Atualizar do ASP.NET para o ASP.NET Core.

Adicionar configuração de um assembly externo

Uma implementação IHostingStartup permite adicionar melhorias a um aplicativo durante a inicialização de um assembly externo fora da classe Startup do aplicativo. Para obter mais informações, confira Usar assemblies de inicialização de hospedagem no ASP.NET Core.

Recursos adicionais

configuração do ponto de extremidade Kestrel

configuração de ponto de extremidade específica Kestrel substitui todas as configurações de ponto de extremidade entre servidores. As configurações de ponto de extremidade entre servidores incluem:

Considere o seguinte arquivo appsettings.json usado em um aplicativo Web ASP.NET Core:

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

Quando a marcação realçada anterior é usada em um aplicativo Web ASP.NET Core e o aplicativo é iniciado na linha de comando com a seguinte configuração de ponto de extremidade entre servidores:

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

Kestrel se liga ao ponto de extremidade configurado especificamente para Kestrel no arquivo appsettings.json (https://localhost:9999) e não no https://localhost:7777.

Considere o ponto de extremidade específico Kestrel configurado como uma variável de ambiente:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

Na variável de ambiente anterior, Https é o nome do ponto de extremidade específico do Kestrel. O arquivo appsettings.json anterior também define um ponto de extremidade específico Kestrel chamado Https. Por padrão, as variáveis de ambiente que usam o provedor de configuração de variáveis de ambiente são lidas após appsettings.{Environment}.json, portanto, a variável de ambiente anterior é usada para o ponto de extremidade Https.

GetValue

ConfigurationBinder.GetValue extrai um valor de configuração com uma chave especificada e o converte para o tipo especificado. O método é um método de extensão 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}");
    }
}

No código anterior, se NumberKey não for encontrado na configuração, será usado o valor padrão 99.

GetSection, GetChildren e Exists

Para os exemplos a seguir, considere o seguinte arquivo MySubsection.json:

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

O código a seguir adiciona MySubsection.json aos provedores de configuração:

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 returna uma subseção de configuração com a chave de subseção especificada.

O código a seguir retorna valores para 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"]}'");
    }
}

O código a seguir retorna valores para 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 retorna null. Se uma seção correspondente não for encontrada, um IConfigurationSection vazio será retornado.

Quando GetSection retorna uma seção correspondente, Value não é preenchido. Key e Path são retornados quando a seção existe.

GetChildren e Exists

O código a seguir chama IConfiguration.GetChildren e retorna valores para 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);
    }
}

O código anterior chama ConfigurationExtensions.Exists para verificar se a seção existe:

Associar uma matriz

O ConfigurationBinder.Bind dá suporte a matrizes de associação para objetos usando os índices em chaves de configuração. Qualquer formato de matriz que exponha um segmento de chave numérica é capaz de associar matrizes a uma matriz de classe POCO.

Considere MyArray.json do download de exemplo:

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

O código a seguir adiciona MyArray.json aos provedores de configuração:

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

O código a seguir lê a configuração e exibe os 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);
    }
}

O código anterior retorna a saída a seguir:

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

Na saída anterior, o Índice 3 tem valor value40, correspondendo a "4": "value40", no MyArray.json. Os índices de matriz vinculados são contínuos e não vinculados ao índice de chave de configuração. O associador de configuração não é capaz de vincular valores nulos ou criar entradas nulas em objetos vinculados

O código a seguir carrega a configuração array:entries com o método de extensão 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>();
            });
    }
}

O código a seguir lê a configuração no arrayDictDictionary e exibe os 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);
    }
}

O código anterior retorna a saída a seguir:

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

O Índice 3 no objeto vinculado contém os dados de configuração da chave de configuração array:4 e seu valor de value4. Quando os dados de configuração que contêm uma matriz são associados, os índices da matriz nas chaves de configuração são usados para iterar os dados de configuração ao criar o objeto. Um valor nulo não pode ser mantido nos dados de configuração, e uma entrada de valor nulo não será criada em um objeto de associação quando uma matriz nas chaves de configuração ignorar um ou mais índices.

O item de configuração ausente para o índice nº 3 pode ser fornecido antes da associação à instância ArrayExamplepor qualquer provedor de configuração que leia o par chave/valor do índice nº 3. Considere o seguinte arquivo Value3.json do download de exemplo:

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

O código a seguir inclui a configuração para Value3.json e 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>();
            });
    }
}

O código a seguir lê a configuração anterior e exibe os 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);
    }
}

O código anterior retorna a saída a seguir:

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

Provedores de configuração personalizados não são necessários para implementar a associação de matriz.

Provedor de Configuração personalizado

O aplicativo de exemplo demonstra como criar um provedor de configuração básico que lê os pares chave-valor da configuração de um banco de dados usando Entity Framework (EF).

O provedor tem as seguintes características:

  • O banco de dados EF na memória é usado para fins de demonstração. Para usar um banco de dados que exija uma cadeia de conexão, implemente um ConfigurationBuilder secundário para fornecer a cadeia de conexão de outro provedor de configuração.
  • O provedor lê uma tabela de banco de dados na configuração na inicialização. O provedor não consulta o banco de dados em uma base por chave.
  • O recarregamento na alteração não está implementado, portanto, a atualização do banco de dados após a inicialização do aplicativo não tem efeito sobre a configuração do aplicativo.

Defina uma entidade EFConfigurationValue para armazenar valores de configuração no banco de dados.

Models/EFConfigurationValue.cs:

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

Adicione um EFConfigurationContext para armazenar e acessar os valores configurados.

EFConfigurationProvider/EFConfigurationContext.cs:

// using Microsoft.EntityFrameworkCore;

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

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

Crie uma classe que implementa 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);
    }
}

Crie o provedor de configuração personalizado através da herança de ConfigurationProvider. O provedor de configuração inicializa o banco de dados quando ele está vazio. Como as chaves de configuração não diferenciam maiúsculas de minúsculas, o dicionário usado para inicializar o banco de dados é criado com o comparador que não diferencia maiúsculas de minúsculas (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;
    }
}

Um método de extensão AddEFConfiguration permite adicionar a fonte de configuração a um 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));
    }
}

O código a seguir mostra como usar o EFConfigurationProvider personalizado no Program.cs :

// using Microsoft.EntityFrameworkCore;

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

Acessar configuração na Inicialização

O código a seguir exibe os dados de configuração nos 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 obter um exemplo de como acessar a configuração usando os métodos de conveniência de inicialização, consulte Inicialização do aplicativo: métodos de conveniência.

Acessar configuração no Razor Pages

O código a seguir exibe os dados de configuração em um Razor Page:

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

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

No código a seguir, MyOptions é adicionada ao contêiner de serviço com Configure e associada à configuração:

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

    services.AddRazorPages();
}

A marcação a seguir usa a diretiva @injectRazor para resolver e exibir os valores de opções:

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

Acessar a configuração em um arquivo de visualização MVC

O código a seguir exibe os dados de configuração em uma visualização MVC:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

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

Configurar opções com um delegado

As opções configuradas em um delegado substituem os valores definidos nos provedores de configuração.

A configuração de opções com um delegado é demonstrada no Exemplo 2 no aplicativo de exemplo.

No código a seguir, um serviço IConfigureOptions<TOptions> é adicionado ao contêiner de serviço. Ele usa um delegado para configurar valores para MyOptions:

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

    services.AddRazorPages();
}

O código a seguir exibe os valores das opções:

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

No exemplo anterior, os valores de Option1 e Option2 são especificados em appsettings.json e substituídos pelo delegado configurado.

Configuração do host versus do aplicativo

Antes do aplicativo ser configurado e iniciado, um host é configurado e iniciado. O host é responsável pelo gerenciamento de tempo de vida e pela inicialização do aplicativo. O aplicativo e o host são configurados usando os provedores de configuração descritos neste tópico. Os pares chave-valor de configuração do host também estão incluídos na configuração do aplicativo. Para obter mais informações sobre como os provedores de configuração são usados quando o host é compilado e como as fontes de configuração afetam a configuração do host, confira Visão geral dos fundamentos do ASP.NET Core.

Configuração de host padrão

Para obter detalhes sobre a configuração padrão ao usar o host da Web, confira a versão do ASP.NET Core 2.2 deste tópico.

  • A configuração do host é fornecida de:
    • Variáveis ​​de ambiente prefixadas com DOTNET_ (por exemplo, DOTNET_ENVIRONMENT) usando o provedor de configuração de variáveis ​​de ambiente. O prefixo (DOTNET_) é removido durante o carregamento dos pares chave-valor de configuração.
    • Argumentos de linha de comando usando o Provedor de configuração de linha de comando.
  • A configuração padrão do host da Web foi estabelecida (ConfigureWebHostDefaults):
    • O Kestrel é usado como o servidor Web e configurado usando provedores de configuração do aplicativo.
    • Adicione o middleware de filtragem de host.
    • Adicione o middleware de cabeçalhos encaminhados se a variável de ambiente ASPNETCORE_FORWARDEDHEADERS_ENABLED for definida para true.
    • Habilite a integração de IIS.

Outra configuração

Este tópico refere-se apenas à configuração do aplicativo. Outros aspectos da execução e hospedagem de aplicativos ASP.NET Core são configurados usando arquivos de configuração não abordados neste tópico:

As variáveis de ambiente definidas em launchSettings.json substituem as definidas no ambiente do sistema.

Para saber mais sobre como migrar a configuração do aplicativo de versões anteriores do ASP.NET, confira Atualizar do ASP.NET para o ASP.NET Core.

Adicionar configuração de um assembly externo

Uma implementação IHostingStartup permite adicionar melhorias a um aplicativo durante a inicialização de um assembly externo fora da classe Startup do aplicativo. Para obter mais informações, confira Usar assemblies de inicialização de hospedagem no ASP.NET Core.

Recursos adicionais