Dissecando o AppSetings.json

Entendendo o appsettings e o deploy em vários ambientes

Com o .Net Framework se aposentando e entrando em jogo o .Net Core (agora só .Net), você já deve ter notado que algumas coisinhas mudaram na estrutura de seus projetos. Uma dessas coisas foram a troca dos arquivos de configuração web.config/app.config, pelo appsettings.json.

Ok, mas qual é a desse cara?

Para responder isso primeiramente vamos criar um projeto webapi no Visual Studio, ou se preferir pelo cli do dotnet. Já na raiz do nosso projeto vemos o arquivo appsettings.json e também o appsettings.Development.json.

Raiz Projeto

E aí fazemos nossa primeira pergunta porque esses dois arquivos?

Bom, imagine que você tenha três ambientes, um ambiente para desenvolvimento, um ambiente para testes e QA e por último e não menos importante um ambiente de produção, e que cada um desses tenha configurações diferentes, seja uma connection string, um endereço de uma api externa...

É nesse cenário que entra estes diferentes arquivos appsettings, vale a nossa atenção que há um padrão de nomenclatura entre eles appsettings.[Environment].json, sendo o environment o nome do ambiente que o appsettings irá sobrescrever e/ou adicionar as configurações.

Tá, mas se tem um padrão de nomenclatura porque tem um arquivo que não tem o ambiente no nome?? 😒

Excelente pergunta caro padawan, mas vou responde-la mais à frente.

Para melhor entendimento do nosso exemplo vamos criar então um appsettings para cada um dos três ambientes, no final teremos então appsettings.json, appsettings.Development.json, appsettings.Staging.json, appsettings.Production.json, com os seguintes códigos:

No appsettings.json :

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

E nos demais appsettings:

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

Com os arquivos criados podemos prosseguir, o arquivo appsettings.json é o arquivo de configuração default do .Net, e quando temos outros arquivos com diferentes ambientes, o .Net faz o merge do appsettings.json com o appsettings.[Environment].json, sacou?

E como o .Net vai saber com qual arquivo deve ser feito o merge??

O .Net usa como referência a variável "ASPNETCORE_ENVIRONMENT" que é uma variável de ambiente, ela pode ser criada diretamente no Windows, ou podemos informa-la através do launchSettings.json e também na hora que estamos buildando/publicando nossa aplicação.

Vamos criar algumas propriedades nos appsettings e adicionar os perfis que vamos utilizar no lauchSettings. Removi algumas props que não são relevantes para nosso estudo atual e adicionei as que vamos usar. Nosso código ficará assim:

appsettings.json

{
  "PropCompartilhada": "esta propriedade será a mesma em todos os ambientes.",
  "PropRescrita": "esta propriedade está sendo reescrita pelo ambiente: ",
  "AllowedHosts": "*"
}

appsettings.Development.json

{
  "PropDev":  "Sou uma propriedade exclusiva de Dev",
  "PropRescrita": "Esta propriedade está sendo reescrita pelo ambiente: Dev"
}

appsettings.Staging.json

{
  "PropStaging": "Sou uma propriedade exclusiva de Staging",
  "PropRescrita": "esta propriedade está sendo reescrita pelo ambiente: Staging"
}

appsettings.Production.json

{
  "PropProd": "Sou uma propriedade exclusiva de Prod",
  "PropRescrita": "esta propriedade está sendo reescrita pelo ambiente: Prod"
}

launchSettings.json

{
  "profiles": {
    "ExemploAppSettings - Prod": {
      "commandName": "Project",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Production"
      },
      "applicationUrl": "http://localhost:5057"
    },
    "ExemploAppSettings - QA": {
      "commandName": "Project",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Staging"
      },
      "applicationUrl": "http://localhost:5057"
    },
    "ExemploAppSettings - Dev": {
      "commandName": "Project",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "http://localhost:5057"
    }
  },
  "$schema": "https://json.schemastore.org/launchsettings.json",
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:35912",
      "sslPort": 44319
    }
  }
}

No arquivo launchSettings.json setamos a variável ASPNETCORE_ENVIRONMENT com o ambiente que vamos executar nossa aplicação, então para finalizarmos a parte de código e testarmos a aplicação vamos exibir as propriedades na tela do browser com o código abaixo:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

var props = $@"Prop compartilhada pelo appsettings: {app.Configuration.GetValue<string>("PropCompartilhada")} 
Prop reescrita pelo ambiente: {app.Configuration.GetValue<string>("PropReescrita")} 
Prop exclusiva de Dev: {app.Configuration.GetValue<string>("PropDev")} 
Prop exclusiva de Qa: {app.Configuration.GetValue<string>("PropStaging")} 
Prop exclusiva de Prod: {app.Configuration.GetValue<string>("PropProd")}";

app.MapGet("/", () => props);

app.Run();

Executando o projeto com o perfil ExemploAppSettings - Dev temos a seguinte saída no browser:

Saída Ambiente Dev

Note que a propriedade compartilhada segue com o mesmo valor, a sobrescrita foi realmente sobrescrita pelo valor do ambiente de dev, a exclusiva de dev foi printada na tela e as demais não foram obtidas pois não foram mergeadas ao appsettings padrão.

E é assim pros demais ambientes:

Ambiente de QA: Saída Ambiente QA

Ambiente de Prod: Saída Ambiente Prod

Concluindo, vimos que o .Net tem um arquivo de configuração padrão o qual conseguimos sobrescrevê-lo e até adicionar novos valores a ele criando novos arquivos de configuração seguindo o padrão appsettings.[Environment].json, para e para executarmos o projeto com as configurações de ambiente desejadas basta adicionarmos um perfil de execução setando a variável de ambiente ASPNETCORE_ENVIRONMENT com o ambiente desejado.
Para publicarmos o projeto seguindo as configurações do ambiente desejado basta executarmos o seguinte código:

dotnet publish -c Release -o /app/publish /p:EnvironmentName=Staging

Bom esse foi meu primeiro post, espero que tenha sido útil prometo melhorar nos próximos rsrsrs. Para mais informações sobre o appsettings e a publicação em vários ambientes segue a documentação utilizada como base deste post.

Até breve!