產品從開發到正式上線的過程中,通常都會有很多個環境,如:開發環境、測試環境及正式環境等。
每個環境的組態設定可能都略有不同,至少資料庫不會都連到同一個地方,因此就會有不同環境組態設定的需求。
ASP.NET Core 就提供了相關的環境 API,透過環境 API 取得執行環境的資訊,進而做對應處理。
本篇將介紹 ASP.NET Core 的多重環境組態管理。
同步發佈至個人部落格:
John Wu's Blog - [鐵人賽 Day16] ASP.NET Core 2 系列 - 多重環境組態管理 (Multiple Environments)
環境 API 可以讀取執行程式的環境資訊,例如:環境名稱、網站實體路徑、網站名稱等。
其中環境名稱就是用來判斷執行環境的主要依據,環境名稱是從系統變數為 ASPNETCORE_ENVIRONMENT
的內容而來。
ASP.NET Core 預設將環境分為三種:
要取得系統變數 ASPNETCORE_ENVIRONMENT
,可以透過注入 IHostingEnvironment
API。範例如下:
Startup.cs
// ...
public class Startup
{
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
env.EnvironmentName = EnvironmentName.Development;
if (env.IsDevelopment()) {
// Do something...
}
app.Run(async (context) =>
{
await context.Response.WriteAsync(
$"EnvironmentName: {env.EnvironmentName}\r\n"
+ $"IsDevelopment: {env.IsDevelopment()}"
);
});
}
}
網站啟動時,IHostingEnvironment
會從系統變數 ASPNETCORE_ENVIRONMENT
取得資料後,填入 EnvironmentName
,該值也可以從程式內部直接指派。
環境名稱並沒有特定的限制,它可以是任意的字串,不一定要被預設的三種分類限制。
例如自訂一個 Test 的環境。如下:
Startup.cs
// ...
public class Startup
{
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
env.EnvironmentName = "Test";
if (env.IsDevelopment()) {
// Do something...
} else if (env.IsEnvironment("test")) {
// Do something...
}
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
{
"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
{
"DBConnectionString": "Data Source=192.168.1.5;Initial Catalog=MyWebsite;Persist Security Info=True;User ID=xxx;Password=xxx"
}
載入組態設定方式:
Program.cs
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 也可以用指令:
SETX ASPNETCORE_ENVIRONMENT "Production" /M
需要用系統管理員權限執行。
如果設定完沒有生效,試著重新登入或重開機。
Linux\macOS 可以在 /etc/profile
加入環境變數:
export ASPNETCORE_ENVIRONMENT="Production"
IIS 的 Web.config 也可以設定環境變數:
Web.config
<?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>
如果是用 VS Code 開發的話,可以在 launch.json 找到 ASPNETCORE_ENVIRONMENT
的設定如下:
launch.json
{
"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 2017),可以從 UI 設定環境名稱。如下:
或者從 Properties\launchSettings.json 設定:
Properties\launchSettings.json
{
// ...
"profiles": {
// ...
"MyWebsite": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Local"
},
"applicationUrl": "http://localhost:5000/"
}
}
}
用 Visual Studio 2017 啟動網站後,就會套用該設定的環境名稱。如下:
Working with multiple environments