ASP.NET和ASP.NETCore多環境配置對比
- 2022 年 4 月 16 日
- 筆記
- .NET Core, aspnetcore, c#
前言
多環境配置應該都很熟悉了,最為常見的便是Debug
和Release
,例如下圖是新建的一個asp.net
項目,配置文件展開共有三個文件組成
據我所知,大多公司從來沒編輯過Web.Debug.config
和Web.Release.config
,一個Web.config
文件改來改去來切換不同的配置,十分麻煩。
asp.net下的多環境配置
哪怕你隨手雙擊打開Web.Debug.config
和Web.Release.config
任何一個,看看裏面的注釋。
Web.Debug.config
<?xml version="1.0" encoding="utf-8"?>
<!-- 有關使用 Web.config 轉換的詳細信息,請訪問 //go.microsoft.com/fwlink/?LinkId=301874 -->
<configuration xmlns:xdt="//schemas.microsoft.com/XML-Document-Transform">
<!--
在下例中,「SetAttributes」轉換將更改
「connectionString」的值,僅在「Match」定位器找到值為「MyDB」的
特性「name」時使用「ReleaseSQLServer」。
<connectionStrings>
<add name="MyDB"
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
-->
<system.web>
<!--
在以下示例中,"Replace" 轉換將替換 Web.config 文件的
整個 <customErrors> 節。
請注意,由於在 <system.web> 節點下只有一個
customErrors 節,因此無需使用 "xdt:Locator" 屬性。
<customErrors defaultRedirect="GenericError.htm"
mode="RemoteOnly" xdt:Transform="Replace">
<error statusCode="500" redirect="InternalError.htm"/>
</customErrors>
-->
</system.web>
</configuration>
微軟為了讓你使用它,把不僅給出實例,還配上詳細的注釋。
下面再展示下最為常用的appSettings
如何配置
Web.config // 開發環境
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="MyKey" value="Myvalue" />
</appSettings>
Web.Release.config // Release環境
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="MyKey" value="Releasvalue" xdt:Transform="Replace" xdt:Locator="Match(key)" />
</appSettings>
經過這樣的配置後,本機開發時讀取到MyKey
的值為Myvalue
,發佈生產環境時值為Releasvalue
。
按照上面的配置,本地發佈一下試試。
發佈成功後,打開發佈後的Web.config
文件,我們發現開發環境下Web.config
中對應的值被替換了。
如何增加額外的環境配置
有時候Debug和Release兩個環境還不能滿足我們的需要,需要增加更多的環境配置。
打開菜單生成–>配置管理器,新建一個TEST1環境
然後右鍵Web.config
選擇添加配置轉換
(第四個)
會自動生成一個Web.TEST1.config
文件,添加一個該環境下的配置用來覆蓋開發配置
更改發佈的配置
打開發佈成功後的Web.config
文件
效果與預期一致。
aspnetcore下的多環境配置
aspnetcore中的配置文件被appsettings.json
所取代,.NET Core中的配置是使用一個或多個配置提供程序執行的。 配置提供程序使用各種配置源從鍵值對讀取配置數據:
什麼是配置提供程序
下表顯示了 .NET Core 應用可用的配置提供程序。
提供程序 | 通過以下對象提供配置 |
---|---|
Azure 應用配置提供程序 | Azure 應用程序配置 |
Azure Key Vault 配置提供程序 | Azure Key Vault |
命令行配置提供程序 | 命令行參數 |
自定義配置提供程序 | 自定義源 |
環境變量配置提供程序 | 環境變量 |
文件配置提供程序 | JSON、XML 和 INI 文件 |
Key-per-file 配置提供程序 | 目錄文件 |
內存配置提供程序 | 內存中集合 |
應用機密(機密管理器) | 用戶配置文件目錄中的文件 |
詳細內容參考 .NET 中的配置
//docs.microsoft.com/zh-cn/dotnet/core/extensions/configuration
其中以下部分比較值得注意
劃重點:後來添加的配置提供程序會替代之前的密鑰設置
appsettings.Development.json
比appsettings.json
後加載,則後加載的會覆蓋先加載配置的值,沒毛病!
多環境配置文件時如何加載
為了徹底弄清楚底層加載邏輯,下載源碼一探究竟。
builder.ConfigureAppConfiguration((hostingContext, config) =>
{
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
if (env.IsDevelopment())
{
if (!string.IsNullOrEmpty(env.ApplicationName))
{
var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
if (appAssembly != null)
{
config.AddUserSecrets(appAssembly, optional: true);
}
}
}
config.AddEnvironmentVariables();
if (args != null)
{
config.AddCommandLine(args);
}
})
默認的WebHostBuilder
,用環境變量env.EnvironmentName
拼接的文件就是默認加載的Json境配置文件。
也就解釋了為什麼開發階段會加載appsettings.Development.json
配置文件了。
VS本地開發時如何切換環境
如何傳參修改環境變量EnvironmentName
值是問題的關鍵,若能修改想要的值,然後創建對應名稱的配置文件即可。
在web根目錄存在一個文件:Properties/launchSettings.json
其中有一個配置環境變量的配置
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
本地開發時只需要創建多個啟動配置,分別設置不同的ASPNETCORE_ENVIRONMENT
即可進行切換了,修改後的launchSettings.json
// launchSettings.json
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "//localhost:2364",
"sslPort": 44302
}
},
"profiles": {
"Web1": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "//localhost:7006;//localhost:5006",
"dotnetRunMessages": true
},
"Web1:Test": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "TEST"
},
"applicationUrl": "//localhost:7006;//localhost:5006",
"dotnetRunMessages": true
}
}
}
Web1
和Web1:Test
啟動選項便會同步顯示在VS啟動選項中,切換為Web1:Test
再運行程序,就會加載appsettings.TEST.json
,效果和appsettings.Development.json
沒區別。
如何在發佈時應用不同的配置文件
在上文中我們學會了在本地配置多個不同環境配置進行開發,那如果需要發佈的生產環境也有很多種配置,那如何讓程序自動加載不同的配置文件呢,畢竟launchSettings.json
文件只是在開發時搭配VS用的,既然launchSettings.json
可以配置環境變量,沒了它我們手動創建環境變量應該也可以。在操作系統添加環境變量如:
也可以在程序啟動時通過命令行傳參設置環境值。
但是這兩種我都感覺不方便,我們希望程序根據不同的環境發佈好以後,只需要直接執行就好,而不是需要進行額外的配置或傳參。
EnvironmentName 屬性
在項目的工程文件中有EnvironmentName
屬性,可以指定當前EnvironmentName
值,添加如下代碼
然後編譯後的,直接運行,就能夠讀取到appsettings.TEST.json
配置文件。
這配置不會覆蓋launchSettings.json
中指定的環境值,但在影響發佈後的EnvironmentName
值,從而可以改變實現發佈後默認的EnvironmentName
值。
那這樣設置後,豈不是發佈後的EnvironmentName
值只能是Test
,如果要發佈其他環境還要每次發佈前修改這個值,那不是很麻煩嗎?
沒錯如果沒有點其他手段,那這真是多此一舉啊,請看下圖。
懂了吧,我們只需要多配置一個PublishProfile
發佈文件,指定不同的配置
項,然後結合Condition
條件來控制EnvironmentName
。
至此,完美實現根據不同環境選擇不同的發佈文件,進行發佈項目,目標機器不需要做任何配置,直接運行就是我們想要的效果。
總結雖然ASP.NET和ASP.NETCore實現多環境的方式不同,但是最後發佈時我們可以做到一樣的效果,所有的配置都是一次性的,發佈時指定對應的PublishProfile
即可。