3

Trabalhando com variáveis de ambiente e arquivos de configuração no ASP.NET 5/Core

#.NET Core #.NET C# #.NET 5
Gabriel Faraday
Gabriel Faraday

Imagine que você criou uma api com ASP.NET 5 e você vai ter mais de um ambiente para manter a sua api. Digamos que você tem os seguintes ambientes: dev, qa e prod.


O ambiente dev você utilizará enquanto desenvolvendo a api, então o banco de dados que você vai utilizar estará no servidor fictício A, por exemplo, com suas respectivas credenciais de acesso. 


O ambiente de qa será utilizado pela equipe de testes, então o banco de dados utilizado não pode ser o mesmo de dev, para não “sujar” a massa de dados dos testes, portanto neste ambiente você deve apontar para o servidor B com suas respectivas credenciais de acesso.


E da mesma forma segue para o ambiente de prod, que é o ambiente produtivo, ou seja, utilizado pelos usuários finais da aplicação e que para nosso exemplo estará utilizando o banco de dados no servidor C.


Estou citando aqui banco de dados mas existe uma série de configurações que você pode precisar para uma aplicação e que geralmente serão diferentes para cada ambiente que você for utilizá-la, por exemplo, dados de exchanges e filas do seu message broker, variáveis de configuração para número de retry para uma dada funcionalidade ou minutos para aguardar por dada funcionalidade, e assim por diante. Os cenários são inúmeros.


No ASP.NET existem ao menos duas formas de tratarmos isso, e sobre elas que iremos falar neste artigo!


Para executar o exemplo aqui explanado você precisará ter instalado o .NET 5 (ou maior) - https://dotnet.microsoft.com/download - e o Visual Code - https://code.visualstudio.com/download


Se você quiser conhecer mais sobre o .NET ou sobre como instalar ele em sua máquina, confira o curso de Introdução ao .NET que a DIO disponibiliza em seu portfólio de cursos, ou confira mais informações no meu canal do Youtube: https://www.youtube.com/c/GabrielFaraday



Criando uma api


Vamos inicialmente criar uma api através do seguinte comando na linha de comando (cmd no Windows ou shell no Linux):


dotnet new api -n api-dio


Então acessamos a pasta que o comando criou, já com uma estrutura básica de api criada, e abrimos essa pasta no Visual Code:


cd api-dio

code .


Veremos uma estrutura parecida com a da imagem abaixo:

 


Repare que o comando já traz na estrutura base que ele cria, dois arquivos de configuração: appsettings.json e appsettings.Development.json.


Arquivos de configuração


De maneira bem resumida o que ocorre é o seguinte: lá no arquivo Program.cs é feita uma chamada para Host.CreateDefaultBuilder no momento que a aplicação é inicializada.


Este método irá pré-configurar nossa aplicação preenchendo um objeto singleton em memória que pode ser referenciado em qualquer lugar do nosso código através da injeção da interface IConfiguration (veremos sobre ela mais a frente).


Neste objeto estará presente, além de outras coisas, toda a configuração contida no arquivo appsettings.json e no arquivo appsettings.<ambiente>.json.


Ou seja, quando eu rodar minha aplicação no ambiente Development, as configurações do arquivo appsettings.Development.json estarão presentes no meu objeto de Configuration. Quando eu rodar no ambiente QA, as configurações do arquivo appsettings.QA.json estarão presentes, e assim por diante.


Portanto vamos já criar os dois arquivos de configuração que faltam para nossos ambientes previstos no início deste artigo: appsettings.QA.json e appsettings.Prod.json. Inicialmente eles podem ter o mesmo conteúdo do arquivo de Development.


 


Uma vez que temos o arquivo referente a cada ambiente, vamos incluir neles todas as configurações necessárias referentes a cada ambiente, como por exemplo os dados de acesso a nossos servidores de banco de dados, ou como conhecemos, as connection strings.


Detalhe: para ambientes produtivos não é uma boa prática ter a connection string no arquivo de configuração, pois qualquer pessoa com acesso ao código teria visualização às credenciais de acesso ao banco de dados de produção! Mais a frente veremos como lidar melhor com isso.


Para fins didáticos não irei colocar uma connection string real, apenas irei referenciar o servidor fictício referente a cada ambiente. Com isso teremos o seguinte conteúdo em cada um dos arquivos:


appsettings.Development.json

{
 "ConnectionStrings": {
  "MeuBanco": "A"
 },
 "Logging": {
  "LogLevel": {
   "Default": "Information",
   "Microsoft": "Warning",
   "Microsoft.Hosting.Lifetime": "Information"
  }
 }
}


appsettings.QA.json:

{
 "ConnectionStrings": {
  "MeuBanco": "B"
 },
 "Logging": {
  "LogLevel": {
   "Default": "Information",
   "Microsoft": "Warning",
   "Microsoft.Hosting.Lifetime": "Information"
  }
 }
}


appsettings.Prod.json

{
 "ConnectionStrings": {
  "MeuBanco": "C"
 },
 "Logging": {
  "LogLevel": {
   "Default": "Information",
   "Microsoft": "Warning",
   "Microsoft.Hosting.Lifetime": "Information"
  }
 }
}


Agora como podemos acessar essas configurações no nosso código? Lembra da interface IConfiguration que citei mais acima? Vamos injetá-la em nosso controller WeatherForecastController.cs (vamos utilizar o próprio controller de exemplo que ele cria).


Então no construtor da classe do controller injetamos o IConfiguration (do namespace Microsoft.Extensions.Configuration), vamos substituir o conteúdo do método Get() para retornar o conteúdo da configuração de connection string que criamos e vamos limpar todo o restante que não nos será útil.


Em resumo o conteúdo do controller fica assim:


using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;

namespace api_dio.Controllers
{
  [ApiController]
  [Route("[controller]")]
  public class WeatherForecastController : ControllerBase
  {
    private readonly IConfiguration _configuration;
    public WeatherForecastController(IConfiguration configuration)
    {
      _configuration = configuration;
    }

    [HttpGet]
    public string Get()
    {
      return _configuration["ConnectionStrings:MeuBanco"];
    }
  }
}


Agora, como informar para a aplicação em qual ambiente estamos? Faremos isso através de uma variável de ambiente “ASPNETCORE_ENVIRONMENT”.


Variáveis de ambiente


As variáveis de ambiente (do inglês environment variables) são informações do sistema ou ambiente que a aplicação está rodando. O Windows por exemplo tem várias variáveis de ambiente próprias, inclusive que podemos utilizar para obter informações sobre o sistema.


E nós temos a possibilidade de criar ou alterar o conteúdo de variáveis de ambiente.


Lembra da chamada ao Host.CreateDefaultBuilder no momento que a aplicação é inicializada? Ele vai considerar o valor da variável de ambiente “ASPNETCORE_ENVIRONMENT” para determinar o ambiente que a aplicação está rodando e saber qual appsettings.<ambiente>.json considerar para carregar o objeto do IConfiguration.


Detalhe: todas as variáveis de ambiente do sistema onde a aplicação roda também são carregadas para o objeto do IConfiguration, e podem ser acessadas no nosso código, por exemplo: configuration[“ASPNETCORE_ENVIRONMENT”];


Legal, mas onde eu crio ou preencho essa variável?


No arquivo Properties/launchSettings.json ele cria por padrão dois profiles, e em ambos já tem preenchida a "ASPNETCORE_ENVIRONMENT": "Development". No nosso exemplo nos importa o profile “api_dio”.


Importante: como estamos utilizando o Visual Code, pode ser que ele vai criar um arquivo .vscode/launch.json, e neste arquivo existirá uma configuração “env”, também preenchendo a "ASPNETCORE_ENVIRONMENT". Pode remover essa configuração “env”, pois o valor aqui deste arquivo sobrescreverá a configuração do launchSettings no momento de execução na nossa maquina.


Vamos testar! Mantenha a configuração no launchSettings como Development e execute a aplicação com F5.


Repare no Debug Console do Visual Code que ele entendeu o Hosting environment como Development:


 


Abra o navegador e acesse https://localhost:5001/WeatherForecast, caso apareça alguma mensagem de erro de certificado, questão de segurança, clique em Avançado e em Prosseguir. O resultado é o esperado, ele mostra na tela o valor “A”, referente a connection string de Development.


 


Agora pare a execução da aplicação e altere o valor da variável de ambiente no profile api_dio no launchSettings conforme abaixo e execute a aplicação com F5.


"environmentVariables": {
    "ASPNETCORE_ENVIRONMENT": "QA"
   }


Repare no Debug Console do Visual Code que ele entendeu o Hosting environment como QA:


 


Abra o navegador e acesse https://localhost:5001/WeatherForecast. O resultado é o esperado, ele mostra na tela o valor “B”, referente a connection string de QA.


 

Agora pare a execução da aplicação e altere o valor da variável de ambiente no profile api_dio no launchSettings conforme abaixo e execute a aplicação com F5.


"environmentVariables": {
    "ASPNETCORE_ENVIRONMENT": "Prod"
   }


Repare no Debug Console do Visual Code que ele entendeu o Hosting environment como QA:


 


Abra o navegador e acesse https://localhost:5001/WeatherForecast. O resultado é o esperado, ele mostra na tela o valor “C”, referente a connection string de Prod.


 


Recapitulando


Em aplicações ASP.NET Core ou 5+ conseguimos criar arquivos de configuração separados para cada ambiente que a aplicação irá estar presente e informamos à aplicação qual ambiente considerar através da variável de ambiente “ASPNETCORE_ENVIRONMENT".


Você pode ter ficado na dúvida como indicar essa variável em um ambiente que não seja sua máquina local. Sim, você teria que lá na maquina do ambiente de QA e de Prod criar essa variável de ambiente com os respectivos valores.


Mas hoje em dia tudo isso se simplifica muito com o uso de Docker e orquestradores de containers. Em um próximo artigo meu inclusive irei mostrar como trabalhar com o cenário deste artigo mas subindo a api em um container docker!


E antes de encerrarmos por aqui, conforme citado anteriormente, não é boa prática ter os dados sensíveis de produção (credenciais de acesso, etc) no arquivo de configuração. Então como resolver isso em prod? Usando variáveis de ambientes! Desta forma só quem tem acesso na máquina/ambiente de prod é que vai poder ter acesso a preencher ou alterar os dados sensíveis nas variáveis de ambiente.


0
38

Comentários (1)

0
Belisnalva Jesus

Belisnalva Jesus

07/05/2021 15:40

Boa tarde Professor!! preciso da sua ajuda por favor! a duvida que eu tenho não estão na aula , em video, nem deste artigo.Me adiciona no Linkedin.

Obrigada!