Appsettings.json i Environment Variable

Ten wpis jest dla wszystkich, którzy chcieli by używać pliku appsettings.json i połączyć to na produkcji ze zmiennymi środowiskowymi. Generalnie wszystko działa tak jak jest w dokumentacji ale występuje problem z prawidłowym zrozumieniem jak działają zmienne środowiskowe w windows. Samo przełączenie zmiennej środkowej nie wystarczy aby asp .net core zmienił ustawienia aplikacji.

Problem

Problem oryginalnie wyszedł na Windowsie i raczej wynika z nie wiedzy niż z samego błędnego działania. Chodzi o to gdzie i jak są przechowywane zmienne środowisko i jaki to ma wpływ na aplikację asp.net core. Wydaje się dość oczywistym, że podczas uruchamiania aplikacji sprawdzane są zmienne środowiskowe, jeśli są potrzebne to mają takie wartości jakie były ustawione w systemie. I tak się dzieje z aplikacjami asp.net core. Podczas uruchamiana jest sprawdzona zmienna środowiska (o ile jest) i jest potem wykorzystywana w ramach potrzeb. Gdy się zmieni w systemie to się na pewno nie zmieni w trakcie działania programu, trzeba po prostu uruchomić program jeszcze raz. Jednak czasem mimo tego, że się uruchomi aplikację jeszcze raz to zmienna środowiskowa się nie zmiana. I to jest czasem dość nie oczywiste. A wydaje się prostym tematem.

Rozwiązanie

W tym problemie, który opisałem wyżej jest również odpowiedź na tą zagadkę ale po kolei. Problem z tym, że mimo, że restartujemy aplikację .net, nie dochodzi do zmiany zmiennych środowiskowych polega na tym, że proces pod którym uruchomiliśmy naszą aplikację .net (proces rodzica) już wcześniej pobrał zmienne środowiskowe i ta kopia jest przysyłana dalej do kolejnego procesu, który się uruchamia.

Czyli uruchamiając aplikacje .net z terminala to tak naprawdę używamy tych zmiennych środowiskowych, które pobrał terminal, gdy się uruchamiał (a nie tych systemowych) wiec mimo, że wyłączymy aplikację i zmienimy zmienne środowiskowe to i tak w terminalu będą stare (te poprzednie) i restart aplikacji nic nie da. Należy więc uruchomić aplikację .net z nowej instancji terminala. Nowa instancja pobierze nowe zmienne środowiskowe (niektóre dokumentację o tym wiedzą i piszą aby zawsze zrestartować terminal po wprowadzeniu zmian).

Ta sama zasada dotyczy serwerów HTTP. Np: IIS-a. Aby zmienna środowiska była wzięta pod uwagę musi być zrestartowany serwer IIS. To oczywiście jest problematyczne więc można tam wprowadzić ustawienie do web.config-a, która definiuje zmienne środowiskowe i ich wartości. Po zmianie web.config-a aplikacja na IIS się restartuje i pobierze sobie nowego web.config-a i nową wartość zmiennej środowiskowej.

Ta sama zasada dotyczy każdej aplikacji w której możemy odpalać kolejne aplikacje np: menażer plików(TotalComander, DoubleComander itp).

Dlatego też w, podczas dewelopowania aplikacji w VS 2022 mamy pliki launch.json itd., bo sam VS już sobie pobrał zmienne środowiskowe i zmiana nic nie pomoże więc aby to wszystko było w miarę dobrze ogarnięte to możemy dokonywać zmian w pliku i będzie wszystko dobrze działać. Ale potem mogą być ciekawe przypadki na produkcji : )

Nie musimy tego robić jak odpalamy aplikacje z „palca” w sensie z danego folderu, klikając na plik exe. To jest jednany przypadek, gdy restart aplikacji pomoże i wszystko ładnie za działa.

Różne

Dokumentacja do tego jak używać zmiennych środowikowych w asp .net core jest oczywiście tutaj https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments?view=aspnetcore-6.0. Wszystko jest z nią ok oprócz tego co napisałem wyżej.

Dodatkowo jeśli chodzi o IIS-a to bez restartu serwera można zmieniać zmienne środowiskowe przez pliki web.config w taki sposób

<configuration>
  <system.webServer>
    <aspNetCore .....>
      <environmentVariables>
        <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />
      </environmentVariables>
    </aspNetCore>
  </system.webServer>
</configuration>

lub w pliku applicationHost.config, który jest „piętro wyżej” niż katalog z aplikację

<location path="staging.site.com">
  <system.webServer>
    <aspNetCore>
      <environmentVariables>
        <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Staging" />
      </environmentVariables>
    </aspNetCore>
  </system.webServer>
</location>
<location path="production.site.com">
  <system.webServer>
    <aspNetCore>
      <environmentVariables>
        <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Production" />
      </environmentVariables>
    </aspNetCore>
  </system.webServer>
</location>

więcej szczegółów tutaj https://stackoverflow.com/a/37455594/5816153

Podsumowanie

W Internecie jest dużo informacji ale nie które, które są dość zbierze ze sobą są kompletnie nie połączone. Co oznacza, że próbują rozwiązać zagadkę dlaczego nie działa mi coś w aplikacji asp.net core nie możemy znaleźć odpowiedzi, bo problem jest z IIS-sem albo z terminalem albo z obsługą w danych OS-sie zmiennych środowiskowych.

Powyższy problem teraz już tak często nie występuje, bo kontenery mają izolację i swoje zmienne środowiskowe ale dobrze to wiedzieć jak się coś na szybko robi.