產品從開發到正式上線的過程中,通常都會有很多個環境,如:開發環境、測試環境及正式環境等。 每個環境的組態設定可能都略有不同,至少資料庫不會都連到同一個地方,因此就會有不同環境組態設定的需求。 ASP.NET Core 就提供了相關的環境 API,透過環境 API 取得執行環境的資訊,進而做對應處理。 本篇將介紹 ASP.NET Core 的多重環境組態管理。
iT 邦幫忙 2018 鐵人賽 - Modern Web 組參賽文章:[Day16] ASP.NET Core 2 系列 - 多重環境組態管理 (Multiple Environments)
環境名稱 環境 API 可以讀取執行程式的環境資訊,例如:環境名稱、網站實體路徑、網站名稱等。 其中環境名稱就是用來判斷執行環境的主要依據,環境名稱是從系統變數為 ASPNETCORE_ENVIRONMENT
的內容而來。
ASP.NET Core 預設將環境分為三種:
Development :開發環境Staging :暫存環境(測試環境)Production :正式環境要取得系統變數 ASPNETCORE_ENVIRONMENT
,可以透過注入 IHostingEnvironment
API。範例如下:
Startup.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class Startup { public void Configure (IApplicationBuilder app, IHostingEnvironment env ) { env.EnvironmentName = EnvironmentName.Development; if (env.IsDevelopment()) { } app.Run(async (context) => { await context.Response.WriteAsync( $"EnvironmentName: {env.EnvironmentName} \r\n" + $"IsDevelopment: {env.IsDevelopment()} " ); }); } }
網站啟動時,IHostingEnvironment
會從系統變數 ASPNETCORE_ENVIRONMENT
取得資料後,填入 EnvironmentName
,該值也可以從程式內部直接指派。 環境名稱並沒有特定的限制,它可以是任意的字串,不一定要被預設的三種分類限制。
例如自訂一個 Test 的環境。如下:
Startup.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class Startup { public void Configure (IApplicationBuilder app, IHostingEnvironment env ) { env.EnvironmentName = "Test" ; if (env.IsDevelopment()) { } else if (env.IsEnvironment("test" )) { } app.Run(async (context) => { await context.Response.WriteAsync( $"EnvironmentName: {env.EnvironmentName} \r\n" + $"This is test environment: {env.IsEnvironment("test" )} " ); }); } }
建議判斷環境透過 env.IsEnvironment("EnvironmentName")
,IsEnvironment()
會忽略大小寫差異。
組態設定 組態設定檔可以在不同環境都各有一份,或許大部分的內容是相同的,但應該會有幾個設定是不同的。如:資料庫連線字串。 環境名稱也可以跟組態設定檔混用,利用組態設定檔後帶環境名稱,作為不同環境會取用的組態設定檔。
例如: 有一個組態設定檔為 settings.json ,內容如下:
Configuration\settings.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 { "SupportedCultures" : [ "en-GB" , "zh-TW" , "zh-CN" ] , "CustomObject" : { "Property" : { "SubProperty1" : 1 , "SubProperty2" : true , "SubProperty3" : "This is sub property." } } , "DBConnectionString" : "Server=(localdb)\\mssqllocaldb;Database=MyWebsite;" }
正式環境也建立一個名稱相同的檔案,並帶上環境名稱 settings.Production.json ,內容如下:
Configuration\settings.Production.json
1 2 3 { "DBConnectionString" : "Data Source=192.168.1.5;Initial Catalog=MyWebsite;Persist Security Info=True;User ID=xxx;Password=xxx" }
載入組態設定方式:
Program.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 using System.IO;using Microsoft.AspNetCore;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.Configuration;namespace MyWebsite { public class Program { public static void Main (string [] args ) { BuildWebHost(args).Run(); } public static IWebHost BuildWebHost (string [] args ) { return WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostContext, config) => { var env = hostContext.HostingEnvironment; config.SetBasePath(Path.Combine(env.ContentRootPath, "Configuration" )) .AddJsonFile(path: "settings.json" , optional: false , reloadOnChange: true ) .AddJsonFile(path: $"settings.{env.EnvironmentName} .json" , optional: true , reloadOnChange: true ); }) .UseStartup<Startup>() .Build(); } } }
讀取組態設定檔時,會先讀取 settings.json 並設定 optional=false
,指定該檔為必要檔案;再讀取 settings.{env.EnvironmentName}.json 檔案。 組態檔載入的特性是當遇到 Key 值重複時,後面載入的設定會蓋掉前面的設定。
以此例來說,當 settings.Production.json 載入後,就會把 settings.json 的 DBConnectionString 設定蓋掉,而 settings.json 其它的設定依然能繼續使用。
前篇[鐵人賽 Day15] ASP.NET Core 2 系列 - 組態設定 (Configuration) 有介紹讀取組態設定檔。
環境設定 利用系統變數 ASPNETCORE_ENVIRONMENT
能判斷環境的特性,可以在各環境的電腦設定環境名稱。 當程式佈署到該環境後,運行時就會套用該台電腦的系統變數。
Windows Windows 系統變數的設定方式如下: 控制台 -> 系統及安全性 -> 系統
Windows 也可以用指令:
1 SETX ASPNETCORE_ENVIRONMENT "Production" /M
需要用系統管理員 權限執行。 如果設定完沒有生效,試著重新登入或重開機。
Linux\macOS Linux\macOS 可以在 /etc/profile
加入環境變數:
1 export ASPNETCORE_ENVIRONMENT="Production"
IIS IIS 的 Web.config 也可以設定環境變數:
Web.config
1 2 3 4 5 6 7 8 9 10 11 12 13 <?xml version="1.0" encoding="utf-8" ?> <configuration > <system.webServer > <handlers > <add name ="aspNetCore" path ="*" verb ="*" modules ="AspNetCoreModule" resourceType ="Unspecified" /> </handlers > <aspNetCore processPath ="dotnet" arguments =".\MyWebsite.dll" stdoutLogEnabled ="false" stdoutLogFile =".\logs\stdout" > <environmentVariables > <environmentVariable name ="ASPNETCORE_ENVIRONMENT" value ="Production" /> </environmentVariables > </aspNetCore > </system.webServer > </configuration >
Visual Studio Code 如果是用 VS Code 開發的話,可以在 launch.json 找到 ASPNETCORE_ENVIRONMENT
的設定如下:
launch.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 { "version" : "0.2.0" , "configurations" : [ { "name" : ".NET Core Launch (web)" , "type" : "coreclr" , "env" : { "ASPNETCORE_ENVIRONMENT" : "Development" } , } , ] }
透過 VS Code 啟動 .NET Core Launch (web) 時,就會套用該設定的環境名稱。如下:
Visual Studio IDE 若以 Visual Studio IDE 開發(如 Visual Studio 2017),可以從 UI 設定環境名稱。如下:
或者從 Properties\launchSettings.json 設定:
Properties\launchSettings.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 { "profiles" : { "MyWebsite" : { "commandName" : "Project" , "launchBrowser" : true , "environmentVariables" : { "ASPNETCORE_ENVIRONMENT" : "Local" } , "applicationUrl" : "http://localhost:5000/" } } }
用 Visual Studio 2017 啟動網站後,就會套用該設定的環境名稱。如下:
參考 Working with multiple environments