我們在撰寫 .NET 的時候,有許多「組態設定」可以輕易的透過「環境變數」來進行調整或變更,這裡同時也包含了 ASP.NET Core 內建的許多 ASPNETCORE_ 開頭的內建環境變數名稱,可以幫忙調整許多 .NET 與 ASP.NET Core 的預設行為。今天這篇文章我就來整理一下有哪些可以用!

認識 ASP.NET Core 的宿主環境 (Host)
ASP.NET Core 有兩種宿主環境,不同的宿主環境通常會定義一些環境變數來幫助你調整環境的參數,而環境變數區分成兩個不同的名稱前綴 (Prefix):分別為:
- 
.NET Generic Host 通常用來提供 .NET 應用程式一些重要的基礎設定,例如 Dependency injection (DI)、Logging、Configuration、IHostedService implementations 等等,通常用在背景服務類型的應用程式中。 你在執行 CreateDefaultBuilder()的時候,會載入DOTNET_開頭的環境變數。
 
參見: 介紹幾個 .NET SDK、.NET CLI 與 .NET runtime 執行時的好用環境變數 
 
- 
ASP.NET Core Web Host 除了 .NET 應用程式重要的基礎設定外,執行 AAS.NET Core 網站還需要一些額外的設定,例如網站伺服器相關的設定,像是 Kestrel 或 IISIntegration 之類的。 在載入 WebHostBuilder的時候,會載入ASPNETCORE_開頭的環境變數。
 
參見: ASP.NET Core Web Host 
 
ASP.NET Core Web Host 常見的環境變數
大家應該都知道 ASP.NET Core 內建一套效率極高的 Kestrel 網站伺服器,所有 ASP.NET Core 在執行的時候都少不了它,然而我們在啟動 Kestrel 的時候,就有許多可以設定的地方,以下我列出幾個相對常用的環境變數設定。
- 
ASPNETCORE_ENVIRONMENT
 我想這個應該是每位 ASP.NET Core 開發人員都該知道的環境變數,非常實用! 這個 ASPNETCORE_ENVIRONMENT環境變數會用來幫你切換不同的環境(Environment),透過「環境」的管理,可以幫助你在執行時識別不同環境下的資訊,甚至於可以指定不同環境下的組態或應用程式邏輯。
 
參見: Use multiple environments in ASP.NET Core 
 
- 
ASPNETCORE_URLS
 我們在用 dotnet run啟動 ASP.NET Core 在啟動的時候,會先去查找一個Properties/launchSettings.json檔案,找到裡面的profiles.設定檔名稱.applicationUrl屬性,並以這個屬性指定的host與port來啟動網站,其設定的格式為https://localhost:7087;http://localhost:5046。如下範例:
 {
  "profiles": {
    "w1": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "https://localhost:7087;http://localhost:5046",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}
 然而,在你透過 dotnet publish發行網站後,就不會再去讀取Properties/launchSettings.json檔案,取而代之的,就是去讀取ASPNETCORE_URLS環境變數,而且設定值的格式是一樣的,以下是設定範例:
 ASPNETCORE_URLS=https://+:443;http://+:80
 這裡的 +(加號) 用來綁定本機的所有網路介面 (network interface),而https://預設會自動載入 ASP.NET Core 內建的自簽憑證。
 
注意: 早期的 ASP.NET Core 版本使用 ASPNETCORE_SERVER.URLS環境變數,不過已經棄用,使用上要注意,建議改用ASPNETCORE_URLS環境變數。
 
 
- 
ASPNETCORE_Kestrel__Certificates__Default__Path與ASPNETCORE_Kestrel__Certificates__Default__Password
 如果 ASPNETCORE_URLS環境變數指定了https://通訊協定,預設會自動載入 ASP.NET Core 內建的自簽憑證,不過在正式環境下,我們通常會使用正式憑證,而這兩個環境變數就是為此而生。
 我們可以練習透過 mkcert 快速建立一個 PKCS#12 格式的憑證 (PFX): mkcert -pkcs12 localhost
 
這個命令會產生 localhost.p12檔案,預設密碼為changeit
 
 然後我們就可以設定環境變數如下: ASPNETCORE_Kestrel__Certificates__Default__Path='localhost.p12'
ASPNETCORE_Kestrel__Certificates__Default__Password='changeit'
 
- 
ASPNETCORE_CONTENTROOT
 ASP.NET Core 在啟動的時候,預設會找主程式當前的路徑作為內容(Content)的根目錄,這裡的 Content 指的是 ASP.NET Core 應用程式部署時所有的「內容」,也就是所有的 *.dll所在的那些資料夾內容。
 當你想在啟動應用程式的時候,選用另一個資料夾當作載入組件(assembly)的依據,你才需要指定這個 ASPNETCORE_CONTENTROOT環境變數。
 有個實際的案例是,當你的 ASP.NET Core 應用程式是部署在 Windows 服務時,預設 Windows Service 會以 C:\Windows\System32為工作目錄,這也意謂著你的 ASP.NET Core 應用程式在執行的時候,會無法載入正確的 DLL 檔案,那就是因為CONTENTROOT路徑錯誤導致的。解決方法就是額外指定ASPNETCORE_CONTENTROOT環境變數即可。詳見: Host ASP.NET Core in a Windows Service
 
- 
ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
 這裡的 ASPNETCORE_HOSTINGSTARTUPASSEMBLIES可以指定 ASP.NET Core 應用程式的啟動組件(startup assemblies),他會在應用程式啟動時,自動找出指定組件中的HostingStartupattribute,並在應用程式啟動時執行特定程式碼!
 ASPNETCORE_HOSTINGSTARTUPASSEMBLIES=Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation
 
多個組件請用 ;(分號) 分隔不同組件!
 
 這是一種在 .NET 環境下動態載入程式碼的一種進階技巧,詳見 Use hosting startup assemblies in ASP.NET Core 文章說明。 
參見: 啟用 Razor 執行階段編譯 (Enable Razor runtime compilation) 技術細節探索 
 
- 
ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES
 由於 hosting startup assemblies 可以寫死在程式中: public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseSetting(
                    WebHostDefaults.HostingStartupExcludeAssembliesKey,
                    "{ASSEMBLY1;ASSEMBLY2; ...}")
                .UseStartup<Startup>();
        });
 如果你想要在啟動時動態排除特定組件,就可以使用 ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES這個環境變數。
 
- 
ASPNETCORE_PREVENTHOSTINGSTARTUP
 如果你想要在啟動時完全關閉 hosting startup assemblies 機制,就可以使用 ASPNETCORE_PREVENTHOSTINGSTARTUP這個環境變數。
 ASPNETCORE_PREVENTHOSTINGSTARTUP=1
 
- 
ASPNETCORE_HTTP_PORTS
 這個環境變數可以讓你在啟動 ASP․NET Core 應用程式時,透過這個 ASPNETCORE_HTTP_PORTS環境變數來指定預設的HTTP連接埠。
 如果有多個 Ports 可以用分號分隔,例如:ASPNETCORE_HTTP_PORTS=80;8080。
 
- 
ASPNETCORE_HTTPS_PORTS
 當你使用了 HTTPS Redirection Middleware (UseHttpsRedirection) 強迫將所有 HTTP 要求自動轉向到 HTTPS 通訊協定,預設會自動轉向到 Port443,如果不是這個 Port 的話,就要透過ASPNETCORE_HTTPS_PORTS環境變數來指定。
 ASPNETCORE_HTTPS_PORT=443;8443
 或是你也可以將 https_port設定加在appsettings.json設定檔中:
 {
  "https_port": 443,
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}
 
- 
ASPNETCORE_SHUTDOWNTIMEOUTSECONDS
 當 ASP.NET Core 應用程式呼叫 IApplicationLifetime.ApplicationStopping 或在嘗試停止應用程式的過程,因為特定原因導致無法關閉時,可以設定等待幾秒就要強制關閉!(預設 5秒)
 ASPNETCORE_SHUTDOWNTIMEOUTSECONDS=10
 
- 
ASPNETCORE_STARTUPASSEMBLY
 在 ASP.NET Core 5 之前都有個 Startup類別,雖然在 ASP.NET Core 6 的 Minimal APIs 看不到了,但事實上你還是可以定義這個類別,並使用早期的 API 進行定義。如果你想將Startup類別寫在完全不同的另一個組件下,就可以利用ASPNETCORE_STARTUPASSEMBLY環境變數來動態指定啟動類別 (Startup class),非常方便!
 
- 
ASPNETCORE_WEBROOT
 在 ASP.NET Core 網站中,如果要載入靜態網站資源,預設都會放在 wwwroot資料夾下,而這個資料夾名稱可以很簡單的透過ASPNETCORE_WEBROOT環境變數來改變,完全不用修改程式碼。
 ASPNETCORE_WEBROOT=public
 
一些相對罕見的環境變數
- 
ASPNETCORE_TEMP
 在 ASP.NET Core 的核心程式中,所有會用到「暫存資料夾」的地方,都會優先判斷式否有這個 ASPNETCORE_TEMP環境變數,如果有的話,就會以環境變數指定的資料夾路徑作為暫存檔案的存放地點。如果沒有,就會直接呼叫Path.GetTempPath()取得系統預設的暫存資料夾。
 ASPNETCORE_TEMP=G:\TEMP
 
- 
ASPNETCORE_FORWARDEDHEADERS_ENABLED
 如果你想在 Kesntel 前面加上一個負載平衡器,而且負載平衡器不是用 IIS 的話,你就可能會用到這個環境變數。 詳細的用法參見 Forward the scheme for Linux and non-IIS reverse proxies 文章說明。 ASPNETCORE_FORWARDEDHEADERS_ENABLED=true
 如果你的網站部署在 Azure App Service on Linux 或 Web App for Containers 上,也只要在「應用程式設定」的地方加入一個 ASPNETCORE_FORWARDEDHEADERS_ENABLED=true設定到網站上即可,程式完全不用修改就可以啟用。參見: Forwarded Headers Middleware Updates in .NET Core 3.0 preview 6
 
ASP.NET Core Module (ANCM) for IIS 相關環境變數
- 
ASPNETCORE_PORT
 這個環境變數只會用在與 IIS 整合的時候,IIS 在啟動 Kestrel 的時候,會偷偷傳入這個環境變數,用來指定 Out of proccess 運作的 Kestrel 要跑在哪個 Port 上面。 
注意: 你幾乎不會自行設定這個環境變數! 
 
- 
ASPNETCORE_APPL_PATH
 這個環境變數只會用在與 IIS 整合的時候,IIS 在啟動 Kestrel 的時候,會偷偷傳入這個環境變數,用來指定應用程式所在路徑。 
注意: 你幾乎不會自行設定這個環境變數! 
 
- 
ASPNETCORE_TOKEN
 這個環境變數只會用在與 IIS 整合的時候,IIS 在啟動 Kestrel 的時候,會偷偷傳入這個環境變數,用來指定 IIS 與 Kestrel 之間的 Token。 
注意: 你幾乎不會自行設定這個環境變數! 
 
- 
ASPNETCORE_IIS_HTTPAUTH
 這個環境變數只會用在與 IIS 整合的時候,IIS 在啟動 Kestrel 的時候,會偷偷傳入這個環境變數,用來指定 Kestrel 該如何處理 AUTH 要求。 
注意: 你幾乎不會自行設定這個環境變數! 
 
- 
ASPNETCORE_IIS_WEBSOCKETS_SUPPORTED
 這個環境變數只會用在與 IIS 整合的時候,IIS 在啟動 Kestrel 的時候,會偷偷傳入這個環境變數,用來告訴 Kestrel 這台 IIS 是否支援 WebSockets 協定。 
注意: 你幾乎不會自行設定這個環境變數! 
 
- 
ASPNETCORE_MODULE_DEBUG
 當你在 Visual Studio 使用 IIS Express 開發時,這個環境變數可以讓你將 ASP.NET Core Module 的偵錯資訊輸出到 Console 畫面上。 ASPNETCORE_MODULE_DEBUG=console
 
已經不再使用的環境變數
- 
ASPNETCORE_SERVER.URLS
 這個環境變數已經被 ASPNETCORE_URLS取代。
 
- 
ASPNET_ENV
 這個環境變數已經被 ASPNETCORE_ENVIRONMENT取代。
 
- 
Hosting:Environment
 這個環境變數已經被 ASPNETCORE_ENVIRONMENT取代。
 
- 
ASPNETCORE_MANAGEMENTPORT
 在 ASP.NET Core 5.0 以前,有個 ASPNETCORE_MANAGEMENTPORT環境變數,用來指定健康檢測端點的 Port 埠號要用哪一個,讓正式對外的 Port 與健康檢測的 Port 分開,增強安全性。不過從 ASP.NET Core 6.0 開始,就不太需要這個設定了,直接寫死在程式中就好,如下範例:
 app.MapHealthChecks("/healthz").RequireHost("*:5001");
 
想瞭解 ASP.NET Core 5.0 的設定方式,參見 Health checks in ASP.NET Core | Microsoft Docs 
 
其他可能會用到的環境變數
如果不想載入 ASPNETCORE_ 環境變數
以下範例程式我從 dotnet/aspnetcore Repo 的 src\Hosting\Hosting\test\GenericWebHostBuilderTests.cs 測試程式中擷取出來的,只要將 webHostBulderOptions.SuppressEnvironmentConfiguration 設定為 true 即可。
[Fact]
public void CanSuppressAspNetCoreEnvironmentVariables()
{
    var randomEnvKey = Guid.NewGuid().ToString();
    Environment.SetEnvironmentVariable("ASPNETCORE_" + randomEnvKey, "true");
    using var host = new HostBuilder()
        .ConfigureWebHost(_ => { }, webHostBulderOptions =>
        {
            webHostBulderOptions.SuppressEnvironmentConfiguration = true;
        })
        .Build();
    var config = host.Services.GetRequiredService<IConfiguration>();
    Assert.Null(config[randomEnvKey]);
    Environment.SetEnvironmentVariable("ASPNETCORE_" + randomEnvKey, null);
}
2024-05-05: 補充說明 .NET CLI 的使用技巧
本篇文章介紹的雖然都是 ASP.NET Core 的環境變數,但其實在透過 .NET CLI 執行 ASP.NET Core 應用程式的時候,其實也可以透過命令列的方式直接取代這些環境變數,而且載入的優先權比環境變數高。以下是幾個常見的例子 (以 dotnet run 為例):
- 
啟動網站時指定環境名稱 dotnet MyApp.dll --environment=Production
 
- 
啟動網站時指定網站的網址與埠號 dotnet MyApp.dll --urls="https://localhost:5001;http://localhost:5000"
 
- 
啟動網站時顯示所有的記錄訊息 dotnet MyApp.dll --Logging:Console:LogLevel:Default=Trace
 
- 
啟動網站時載入 Kestrel 所需的 TLS 憑證 dotnet MyApp.dll --Kestrel:Certificates:Default:Path='localhost.p12' --Kestrel:Certificates:Default:Password='changeit' --urls='https://*:5001'
 
- 
啟動網站時變更 ContentRoot 路徑 這個需求在 Host ASP.NET Core in a Windows Service 的時候常見。 dotnet MyApp.dll --contentRoot=g:\publish
 
- 
啟動網站時變更預設的 HTTPS 轉向埠號 當你的 Kestrel 監聽多個 HTTPS Port 時,或是網站位於 Reverse Proxy 後面時,就有可能需要設定這個參數。 dotnet MyApp.dll --urls='https://*:5001;http://*:5000;https://*:5003' --https_port=5003
 
相關連結