Skip to main content

Variáveis de ambiente e appsettings no .NET | Dia a Dia | CSharp

  • Variáveis de ambiente e appsettings no .NET | Dia a Dia | CSharp

Visão geral

No .NET, principalmente em ASP.NET Core, a configuração da aplicação gira em torno de um conceito central: IConfiguration.

A ideia é simples:

  • a aplicação pode ler configuração de várias fontes
  • essas fontes são combinadas
  • a última fonte carregada normalmente sobrescreve a anterior
  • você acessa tudo por uma API única

O próprio ecossistema ASP.NET Core trata configuração como algo unificado, permitindo combinar JSON, variáveis de ambiente, argumentos de linha de comando e outros providers em uma única árvore de configuração .

Na prática, isso resolve um problema importante:

  • você usa appsettings.json para valores comuns
  • usa appsettings.Development.json para ambiente local
  • usa variáveis de ambiente para produção e segredos
  • o código continua lendo do mesmo lugar

O que é IConfiguration

IConfiguration é a abstração usada pelo .NET para acessar configurações da aplicação. Ela permite ler dados vindos de múltiplas fontes, como:

  • appsettings.json
  • appsettings.{Environment}.json
  • variáveis de ambiente
  • argumentos de linha de comando
  • user secrets
  • providers customizados

Essa é exatamente a proposta descrita no material de ASP.NET Core: unificar o acesso a diferentes fontes de configuração, incluindo arquivos JSON, variáveis de ambiente e argumentos .

Exemplo simples:

string? connectionString = builder.Configuration["ConnectionStrings:DefaultConnection"];
string? nomeApi = builder.Configuration["MinhaApi:Nome"];

Repare no padrão:

  • : separa níveis
  • MinhaApi:Nome equivale a um objeto JSON com propriedade interna

Estrutura mental correta

Pense assim:

  • IConfiguration = mecanismo bruto de leitura
  • appsettings.json = fonte de configuração
  • variáveis de ambiente = outra fonte de configuração
  • Options Pattern = forma recomendada de mapear configuração para classes fortemente tipadas

Ou seja:

  • para algo rápido, você pode usar builder.Configuration["Chave"]
  • para algo sério, repetido e organizado, prefira Options

Fontes mais comuns de configuração

appsettings.json

É o arquivo base da aplicação.

Exemplo:

{
"MinhaApi": {
"Nome": "Comandos API",
"TimeoutSegundos": 30,
"AtivarCache": true
},
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=MinhaBase;User Id=sa;Password=123456;"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

Esse é o lugar ideal para:

  • valores padrão
  • configurações não sensíveis
  • estrutura base da aplicação

appsettings.Development.json

É o arquivo específico para desenvolvimento local.

Exemplo:

{
"MinhaApi": {
"Nome": "Comandos API - Dev",
"TimeoutSegundos": 10
},
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=MinhaBaseDev;User Id=sa;Password=123456;"
}
}

Esse arquivo sobrescreve o appsettings.json quando o ambiente ativo é Development.


Variáveis de ambiente

São muito usadas em produção.

Exemplo de chave:

ConnectionStrings__DefaultConnection
MinhaApi__Nome
MinhaApi__TimeoutSegundos

No ambiente, você usa __ no lugar de :.

Então:

  • MinhaApi:Nome no código
  • MinhaApi__Nome na variável de ambiente

Isso é padrão prático do ecossistema .NET para representar seções hierárquicas via environment variables.


User Secrets

Muito útil em desenvolvimento local para segredos.

Exemplos:

  • senha de banco local
  • token de API
  • client secret OAuth
  • chave JWT local

Use isso em vez de deixar segredos no appsettings.Development.json.


Linha de comando

Também pode sobrescrever config:

dotnet run --MinhaApi:Nome="API via CLI"

É menos comum no dia a dia de API web, mas existe.


Ordem de precedência

O ponto mais importante para quem está começando é entender:

não basta ter várias fontes; a ordem importa.

Regra prática:

  • valores carregados depois sobrescrevem os anteriores

No fluxo padrão de uma aplicação ASP.NET Core moderna, a ideia usual é:

  • appsettings.json
  • appsettings.{Environment}.json
  • user secrets em desenvolvimento
  • variáveis de ambiente
  • linha de comando

Na prática, isso significa:

  • um valor no JSON pode ser substituído por outro no JSON do ambiente
  • esse valor pode ser substituído por uma variável de ambiente em produção

Esse modelo de múltiplos providers em camadas é exatamente a base descrita pelo capítulo de configurações do ASP.NET Core .


Ambiente no .NET: Development, Staging, Production

O .NET trabalha fortemente com o conceito de ambiente.

Os nomes mais comuns são:

  • Development
  • Staging
  • Production

Você descobre o ambiente atual assim:

if (builder.Environment.IsDevelopment())
{
Console.WriteLine("Ambiente de desenvolvimento");
}

if (builder.Environment.IsProduction())
{
Console.WriteLine("Ambiente de produção");
}

Também existe:

string environmentName = builder.Environment.EnvironmentName;

Exemplo:

Console.WriteLine(builder.Environment.EnvironmentName);

Como definir o ambiente

A variável mais comum é:

ASPNETCORE_ENVIRONMENT

Também existe:

DOTNET_ENVIRONMENT

Em aplicações web, ASPNETCORE_ENVIRONMENT é a mais vista no dia a dia.

Exemplo no Windows PowerShell:

$env:ASPNETCORE_ENVIRONMENT="Development"
dotnet run

Exemplo no Linux:

export ASPNETCORE_ENVIRONMENT=Development
dotnet run

Exemplo em Docker Compose:

environment:
ASPNETCORE_ENVIRONMENT: Production

Como isso fica em desenvolvimento

Cenário típico:

  • ASPNETCORE_ENVIRONMENT=Development
  • arquivo appsettings.json
  • arquivo appsettings.Development.json
  • user secrets para segredos

Exemplo de appsettings.json

{
"MinhaApi": {
"Nome": "Minha API",
"TimeoutSegundos": 30
},
"ConnectionStrings": {
"DefaultConnection": ""
}
}

Exemplo de appsettings.Development.json

{
"MinhaApi": {
"Nome": "Minha API DEV",
"TimeoutSegundos": 5
}
}

Exemplo de User Secrets

{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=MinhaBaseDev;User Id=sa;Password=SenhaForteAqui;"
}
}

Resultado final em development

A aplicação enxergará algo como:

  • MinhaApi:Nome = "Minha API DEV"
  • MinhaApi:TimeoutSegundos = 5
  • ConnectionStrings:DefaultConnection = valor do User Secrets

Como isso fica em produção

Em produção, o padrão saudável é:

  • ASPNETCORE_ENVIRONMENT=Production
  • appsettings.json com defaults seguros
  • segredos e diferenças do ambiente via variáveis de ambiente ou secret manager externo
  • nunca deixar senha real em arquivo commitado

Exemplo de appsettings.json

{
"MinhaApi": {
"Nome": "Minha API",
"TimeoutSegundos": 30
},
"ConnectionStrings": {
"DefaultConnection": ""
}
}

Variáveis de ambiente no servidor

ASPNETCORE_ENVIRONMENT=Production
MinhaApi__TimeoutSegundos=60
ConnectionStrings__DefaultConnection=Server=sql-prod;Database=MinhaBase;User Id=app;Password=SenhaSuperForte

Resultado final em produção

A aplicação enxergará:

  • MinhaApi:Nome = "Minha API"
  • MinhaApi:TimeoutSegundos = 60
  • ConnectionStrings:DefaultConnection = valor da variável de ambiente

Regra prática de ouro

Use assim:

  • appsettings.json para base comum
  • appsettings.Development.json para ajustes locais
  • User Secrets para segredos em dev
  • variáveis de ambiente para produção
  • Azure Key Vault, AWS Secrets Manager, Doppler, Vault ou similar para ambientes mais maduros

Exemplo real de leitura com builder.Configuration

Program.cs

var builder = WebApplication.CreateBuilder(args);

string? nomeApi = builder.Configuration["MinhaApi:Nome"];
string? timeout = builder.Configuration["MinhaApi:TimeoutSegundos"];
string? connectionString = builder.Configuration["ConnectionStrings:DefaultConnection"];

Console.WriteLine($"Nome API: {nomeApi}");
Console.WriteLine($"Timeout: {timeout}");
Console.WriteLine($"ConnectionString: {connectionString}");

var app = builder.Build();

app.MapGet("/", () => new
{
Nome = builder.Configuration["MinhaApi:Nome"],
Timeout = builder.Configuration["MinhaApi:TimeoutSegundos"]
});

app.Run();

Isso funciona, mas não é a abordagem mais organizada para configurações maiores.


Padrão recomendado: Options Pattern

O próprio material de ASP.NET Core trata o Options Pattern como parte central da gestão de settings .

Esse é o padrão mais limpo.

appsettings.json

{
"MinhaApi": {
"Nome": "Minha API",
"TimeoutSegundos": 30,
"AtivarCache": true
}
}

Classe de configuração

public sealed class MinhaApiOptions
{
public const string SectionName = "MinhaApi";

public string Nome { get; set; } = string.Empty;
public int TimeoutSegundos { get; set; }
public bool AtivarCache { get; set; }
}

Registro no Program.cs

var builder = WebApplication.CreateBuilder(args);

builder.Services
.AddOptions<MinhaApiOptions>()
.Bind(builder.Configuration.GetSection(MinhaApiOptions.SectionName))
.ValidateDataAnnotations()
.ValidateOnStart();

var app = builder.Build();

app.MapGet("/", (Microsoft.Extensions.Options.IOptions<MinhaApiOptions> options) =>
{
var config = options.Value;

return Results.Ok(new
{
config.Nome,
config.TimeoutSegundos,
config.AtivarCache
});
});

app.Run();

Melhorando com validação

Para evitar subir a aplicação com config inválida, valide.

Classe com validação

using System.ComponentModel.DataAnnotations;

public sealed class MinhaApiOptions
{
public const string SectionName = "MinhaApi";

[Required]
public string Nome { get; set; } = string.Empty;

[Range(1, 300)]
public int TimeoutSegundos { get; set; }

public bool AtivarCache { get; set; }
}

Se faltar Nome ou TimeoutSegundos estiver fora do intervalo, a aplicação já falha na inicialização por causa de ValidateOnStart().

Isso é excelente para produção.


Quando usar IOptions, IOptionsSnapshot e IOptionsMonitor

IOptions<T>

Use quando:

  • a config não muda durante a execução
  • leitura simples basta
app.MapGet("/config", (Microsoft.Extensions.Options.IOptions<MinhaApiOptions> options) =>
{
return options.Value;
});

IOptionsSnapshot<T>

Use quando:

  • você quer pegar configuração por request
  • cenário comum em aplicações web
  • útil quando JSON pode ser recarregado

Exemplo em serviço scoped ou controller.

IOptionsMonitor<T>

Use quando:

  • você precisa reagir a mudanças de configuração em tempo de execução
  • singleton precisa acessar valores atualizados

Como o JSON é mapeado para classes

JSON

{
"Email": {
"Host": "smtp.exemplo.com",
"Porta": 587,
"Usuario": "sistema",
"Senha": "abc123"
}
}

Classe

public sealed class EmailOptions
{
public const string SectionName = "Email";

public string Host { get; set; } = string.Empty;
public int Porta { get; set; }
public string Usuario { get; set; } = string.Empty;
public string Senha { get; set; } = string.Empty;
}

Registro

builder.Services
.AddOptions<EmailOptions>()
.Bind(builder.Configuration.GetSection(EmailOptions.SectionName))
.ValidateOnStart();

Como obter valores diretamente em classes e serviços

Jeito rápido com IConfiguration

public sealed class EmailService
{
private readonly IConfiguration _configuration;

public EmailService(IConfiguration configuration)
{
_configuration = configuration;
}

public void ExibirConfig()
{
string? host = _configuration["Email:Host"];
string? porta = _configuration["Email:Porta"];

Console.WriteLine($"{host}:{porta}");
}
}

Funciona, mas espalha strings mágicas.


Jeito melhor com IOptions

using Microsoft.Extensions.Options;

public sealed class EmailService
{
private readonly EmailOptions _options;

public EmailService(IOptions<EmailOptions> options)
{
_options = options.Value;
}

public void ExibirConfig()
{
Console.WriteLine($"{_options.Host}:{_options.Porta}");
}
}

Melhor porque:

  • é tipado
  • facilita manutenção
  • evita typo em chave
  • centraliza a estrutura da config

Exemplo completo prático

appsettings.json

{
"MinhaApi": {
"Nome": "API de Pedidos",
"TimeoutSegundos": 30,
"AtivarCache": true
},
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=Pedidos;User Id=sa;Password=123456;"
}
}

appsettings.Development.json

{
"MinhaApi": {
"Nome": "API de Pedidos DEV",
"TimeoutSegundos": 10
}
}

Classe MinhaApiOptions.cs

using System.ComponentModel.DataAnnotations;

public sealed class MinhaApiOptions
{
public const string SectionName = "MinhaApi";

[Required]
public string Nome { get; set; } = string.Empty;

[Range(1, 300)]
public int TimeoutSegundos { get; set; }

public bool AtivarCache { get; set; }
}

Program.cs

using Microsoft.Extensions.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services
.AddOptions<MinhaApiOptions>()
.Bind(builder.Configuration.GetSection(MinhaApiOptions.SectionName))
.ValidateDataAnnotations()
.ValidateOnStart();

var app = builder.Build();

app.MapGet("/config-bruta", (IConfiguration configuration) =>
{
return Results.Ok(new
{
Nome = configuration["MinhaApi:Nome"],
Timeout = configuration["MinhaApi:TimeoutSegundos"],
AtivarCache = configuration["MinhaApi:AtivarCache"],
Connection = configuration["ConnectionStrings:DefaultConnection"]
});
});

app.MapGet("/config-tipada", (IOptions<MinhaApiOptions> options) =>
{
return Results.Ok(options.Value);
});

app.MapGet("/ambiente", (IHostEnvironment env) =>
{
return Results.Ok(new
{
env.EnvironmentName,
Development = env.IsDevelopment(),
Production = env.IsProduction()
});
});

app.Run();

Como o Program.cs normalmente já vem configurado

Nas versões modernas do ASP.NET Core, o builder padrão já trabalha com configuração integrada. O framework foi desenhado justamente para combinar providers e expor tudo via builder.Configuration .

Ou seja, na maioria dos casos você não precisa sair adicionando manualmente AddJsonFile, AddEnvironmentVariables e similares para o básico.

O comum é só usar:

var builder = WebApplication.CreateBuilder(args);

e depois acessar:

builder.Configuration

Quando você precisa configurar providers manualmente

Quando quer controle maior.

Exemplo:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.Sources.Clear();

builder.Configuration
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.AddCommandLine(args);

Use isso quando:

  • quer limpar providers padrão
  • quer controlar ordem explicitamente
  • quer adicionar provider customizado
  • quer comportamento muito específico

Para iniciante, isso não deve ser o padrão.


reloadOnChange

Quando um appsettings.json está com reloadOnChange: true, o .NET pode recarregar valores quando o arquivo muda.

Exemplo manual:

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

Isso é útil em desenvolvimento e alguns cenários controlados.

Em produção, normalmente você depende mais de variáveis de ambiente ou secret stores do que de editar arquivo no servidor.


Como ficam variáveis hierárquicas

JSON

{
"RabbitMq": {
"Host": "localhost",
"Port": 5672,
"Username": "guest",
"Password": "guest"
}
}

Variáveis de ambiente equivalentes

RabbitMq__Host=localhost
RabbitMq__Port=5672
RabbitMq__Username=guest
RabbitMq__Password=guest

Leitura no código

string? host = builder.Configuration["RabbitMq:Host"];

Connection strings

Existe um padrão muito comum no .NET:

JSON

{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=MinhaBase;User Id=sa;Password=123456;"
}
}

Leitura correta

string? connectionString = builder.Configuration.GetConnectionString("DefaultConnection");

Isso é melhor do que usar a chave direta manualmente.


Exemplo com banco

string connectionString = builder.Configuration.GetConnectionString("DefaultConnection")
?? throw new InvalidOperationException("Connection string 'DefaultConnection' não encontrada.");

Segredos: o que nunca fazer

Nunca faça isso em projeto real:

{
"Jwt": {
"Key": "minha-chave-secreta-de-producao"
}
}

ou:

var senha = "SenhaSuperSecreta123";

Segredos não devem ficar:

  • no código-fonte
  • em arquivo commitado
  • em print
  • em documentação pública

O próprio material do capítulo de settings destaca a necessidade de não manter parâmetros sensíveis versionados no controle de código-fonte .


O que usar para segredos

Em development

  • User Secrets

Em produção

  • variáveis de ambiente
  • Azure Key Vault
  • AWS Secrets Manager
  • HashiCorp Vault
  • secret do Kubernetes
  • recurso equivalente da sua plataforma

Exemplo de User Secrets

Inicializar:

dotnet user-secrets init

Salvar segredo:

dotnet user-secrets set "ConnectionStrings:DefaultConnection" "Server=localhost;Database=MinhaBaseDev;User Id=sa;Password=SenhaSecreta;"

Ler no código:

string? connectionString = builder.Configuration.GetConnectionString("DefaultConnection");

Como saber de onde veio um valor

Isso confunde muito no começo.

Exemplo:

  • você olha o appsettings.json
  • altera algo
  • a aplicação continua com outro valor
  • o motivo pode ser uma variável de ambiente sobrescrevendo

Uma forma simples de investigar:

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

Isso ajuda a enxergar a configuração final resolvida.


Configuração de logging também usa esse sistema

O sistema de logging em ASP.NET Core também pode ser configurado por configuração. Exemplo de appsettings.json:

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
},
"Console": {
"IncludeScopes": true
}
}
}

O uso de Logging:LogLevel e Console:IncludeScopes em appsettings.json aparece de forma prática no material de observabilidade em .NET .

Isso mostra algo importante:

  • configuração da aplicação
  • configuração de logging
  • configuração de providers

Tudo segue a mesma infraestrutura de config.


Exemplo prático de Development e Production no pipeline

É muito comum fazer isso:

var app = builder.Build();

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

app.UseHttpsRedirection();

app.Run();

Esse padrão de tratamento diferente entre desenvolvimento e produção aparece claramente em exemplos de ASP.NET Core 9 .

Na prática:

Development

  • mais diagnóstico
  • erros detalhados
  • ferramentas de dev
  • configurações locais

Production

  • erro genérico
  • HSTS
  • segredos externos
  • foco em segurança e estabilidade

Como eu recomendo organizar um projeto

Estrutura de arquivos

appsettings.json
appsettings.Development.json
Program.cs
Configurations/
MinhaApiOptions.cs
RabbitMqOptions.cs
JwtOptions.cs

Regras

  • tudo que for config estruturada vai para classe Options
  • nome da seção igual ao nome lógico da config
  • segredos fora de arquivos commitados
  • ValidateOnStart() para config crítica
  • GetConnectionString() para connection strings
  • nada de sair lendo chave crua em qualquer lugar

Exemplo de organização limpa

JwtOptions.cs

using System.ComponentModel.DataAnnotations;

public sealed class JwtOptions
{
public const string SectionName = "Jwt";

[Required]
public string Issuer { get; set; } = string.Empty;

[Required]
public string Audience { get; set; } = string.Empty;

[Required]
public string Key { get; set; } = string.Empty;

[Range(1, 1440)]
public int ExpirationMinutes { get; set; }
}

Program.cs

builder.Services
.AddOptions<JwtOptions>()
.Bind(builder.Configuration.GetSection(JwtOptions.SectionName))
.ValidateDataAnnotations()
.ValidateOnStart();

appsettings.json

{
"Jwt": {
"Issuer": "MinhaApi",
"Audience": "MinhaApi.Clientes",
"Key": "",
"ExpirationMinutes": 60
}
}

Produção

Jwt__Key=chave-real-da-producao

Erros comuns de iniciante

1. Colocar segredo em appsettings.json

Errado.

2. Ler tudo com string mágica

Exemplo ruim:

var valor = configuration["MinhaCoisa:MeuCampo:OutroCampo"];

Em excesso, isso vira bagunça.

3. Duplicar config em muitos lugares

A config deve ter um ponto central.

4. Não validar na inicialização

A aplicação sobe e quebra só quando usa a config.

5. Misturar config de ambiente com código

Errado:

if (builder.Environment.IsProduction())
{
string connection = "Server=sql-prod;...";
}
else
{
string connection = "Server=localhost;...";
}

Correto: deixar isso na configuração.

6. Commitar appsettings.Production.json com valores reais

Evite.

7. Esquecer que variável de ambiente sobrescreve JSON

Esse é clássico.


Padrão prático que eu recomendo para você

Para projeto .NET comum:

Desenvolvimento

  • appsettings.json
  • appsettings.Development.json
  • User Secrets para segredo
  • ASPNETCORE_ENVIRONMENT=Development

Produção

  • appsettings.json só com defaults seguros
  • ASPNETCORE_ENVIRONMENT=Production
  • segredos e diferenças via variáveis de ambiente ou cofre de segredos

Código

  • IOptions<T> para configurações estruturadas
  • GetConnectionString() para banco
  • IsDevelopment() e IsProduction() para pipeline e comportamento
  • ValidateOnStart() para config crítica

Exemplo final completo e saudável

appsettings.json

{
"MinhaApi": {
"Nome": "API Orquestradora",
"TimeoutSegundos": 30
},
"ConnectionStrings": {
"DefaultConnection": ""
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

appsettings.Development.json

{
"MinhaApi": {
"Nome": "API Orquestradora DEV",
"TimeoutSegundos": 10
}
}

MinhaApiOptions.cs

using System.ComponentModel.DataAnnotations;

public sealed class MinhaApiOptions
{
public const string SectionName = "MinhaApi";

[Required]
public string Nome { get; set; } = string.Empty;

[Range(1, 300)]
public int TimeoutSegundos { get; set; }
}

Program.cs

using Microsoft.Extensions.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services
.AddOptions<MinhaApiOptions>()
.Bind(builder.Configuration.GetSection(MinhaApiOptions.SectionName))
.ValidateDataAnnotations()
.ValidateOnStart();

string connectionString = builder.Configuration.GetConnectionString("DefaultConnection")
?? throw new InvalidOperationException("Connection string 'DefaultConnection' não encontrada.");

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/error");
app.UseHsts();
}

app.MapGet("/config", (IOptions<MinhaApiOptions> options, IHostEnvironment env) =>
{
return Results.Ok(new
{
Ambiente = env.EnvironmentName,
options.Value.Nome,
options.Value.TimeoutSegundos
});
});

app.Run();

Variáveis de ambiente em produção

ASPNETCORE_ENVIRONMENT=Production
ConnectionStrings__DefaultConnection=Server=sql-prod;Database=MinhaBase;User Id=app;Password=SenhaForte
MinhaApi__TimeoutSegundos=60

Resumo operacional

Use appsettings.json para

  • base da aplicação
  • valores não sensíveis
  • estrutura comum

Use appsettings.Development.json para

  • ajustes locais de desenvolvimento
  • sem segredos reais

Use User Secrets para

  • segredos locais de desenvolvimento

Use variáveis de ambiente para

  • produção
  • container
  • servidor
  • CI/CD
  • secrets

Use IConfiguration para

  • leitura simples e pontual

Use IOptions<T> para

  • configuração séria
  • organização
  • manutenção
  • validação

Use Environment para

  • comportamento diferente entre dev e prod
  • pipeline HTTP
  • debug e segurança

Referências dos arquivos que usei

  • O capítulo Managing Application Settings de ASP.NET Core 9.0 Essentials descreve IConfiguration, providers e o Options Pattern como base do sistema de configuração do ASP.NET Core
  • O mesmo material mostra o padrão de comportamento diferente entre Development e outros ambientes no pipeline HTTP, com UseDeveloperExceptionPage, UseExceptionHandler e UseHsts
  • O livro sobre observabilidade em .NET mostra uso real de appsettings.json para configurar logging, incluindo LogLevel e Console:IncludeScopes