ASP.NET和ASP.NETCore多環境配置對比

gui.h發表於2022-04-16

前言

多環境配置應該都很熟悉了,最為常見的環境便是DebugRelease,例如下圖是新建的一個asp.net專案,配置檔案展開共有三個檔案組成
image.png
有些開發者從來沒了解過Web.Debug.configWeb.Release.config,始終是一個Web.config檔案改來改去來切換不同的配置,但凡有點追求都不能忍受這種煎熬。

asp.net下的多環境配置

雙擊開啟Web.Debug.configWeb.Release.config任何一個,看看裡面的內容。

Web.Debug.config
<?xml version="1.0" encoding="utf-8"?>

<!-- 有關使用 Web.config 轉換的詳細資訊,請訪問 https://go.microsoft.com/fwlink/?LinkId=301874 -->

<configuration xmlns:xdt="http://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>

微軟為了讓我們使用它,把不僅給出示例,還配上詳細的註釋,看過註釋和示例大概就該知道如何進行配置,覆蓋Web.config中的配置。
下面展示下最為常用的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 生產環境-->
  <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
按照上面的配置,本地釋出程式試試效果。
image.png
釋出成功後,開啟發布後生成的Web.config檔案,我們發現開發環境下Web.config中對應的值被替換了,這樣開發和生產配置分別配置在不同檔案,不需要頻繁修改配置檔案切換配置了。
image.png

如何增加額外的環境配置

有時候Debug和Release兩個環境還不能滿足我們的需要,需要增加更多的環境配置。
開啟選單生成-->配置管理器,新建一個TEST1環境
image.png
然後右鍵Web.config選擇新增配置轉換(第四個)
image.png
會自動生成一個Web.TEST1.config檔案,非常的人性化,然後我們在該檔案配置一些引數。
image.png
更改釋出的配置,進行釋出。
image.png
開啟發布成功後的Web.config檔案
image.png
效果與預期一致。

aspnetcore下的多環境配置

aspnetcore中的配置檔案被appsettings.json所取代,.NET Core中的配置是使用一個或多個配置提供程式執行的。 配置提供程式使用各種配置源從鍵值對讀取配置資料:

什麼是配置提供程式

下表顯示了 .NET Core 應用可用的配置提供程式。

提供程式 通過以下物件提供配置
Azure 應用配置提供程式 Azure 應用程式配置
Azure Key Vault 配置提供程式 Azure Key Vault
命令列配置提供程式 命令列引數
自定義配置提供程式 自定義源
環境變數配置提供程式 環境變數
檔案配置提供程式 JSON、XML 和 INI 檔案
Key-per-file 配置提供程式 目錄檔案
記憶體配置提供程式 記憶體中集合
應用機密(機密管理器) 使用者配置檔案目錄中的檔案

詳細內容參考 .NET 中的配置
https://docs.microsoft.com/zh-cn/dotnet/core/extensions/configuration
其中以下部分比較值得注意
image.png
劃重點:後來新增的配置提供程式會替代之前的金鑰設定
appsettings.Development.jsonappsettings.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配置檔案的原理。

開發階段的多環境

如何傳參修改環境變數EnvironmentName值是問題的關鍵,若能修改想要的值,然後建立對應名稱的配置檔案即可。
在web根目錄存在一個檔案:Properties/launchSettings.json
其中有一個配置環境變數的配置

"environmentVariables": {
    "ASPNETCORE_ENVIRONMENT": "Development"
},

本地開發時只需要建立多個啟動配置,分別設定不同的ASPNETCORE_ENVIRONMENT即可進行切換了,修改後的launchSettings.json

// launchSettings.json
{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:2364",
      "sslPort": 44302
    }
  },
  "profiles": {
    "Web1": {
      "commandName": "Project",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "https://localhost:7006;http://localhost:5006",
      "dotnetRunMessages": true
    },
    "Web1:Test": {
      "commandName": "Project",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "TEST"
      },
      "applicationUrl": "https://localhost:7006;http://localhost:5006",
      "dotnetRunMessages": true
    }
  }
}

Web1Web1:Test啟動選項便會同步顯示在VS啟動選項中,切換為Web1:Test再執行程式,就會載入appsettings.TEST.json,效果和appsettings.Development.json沒區別。
image.png

釋出階段的實現多環境配置

在上文中我們學會了在本地配置多個不同環境配置進行開發,那如果需要釋出的生產環境也有很多種配置,那如何讓程式自動載入不同的配置檔案呢,畢竟launchSettings.json檔案只是在開發時搭配VS用的,既然launchSettings.json可以配置環境變數,沒了它我們手動建立環境變數應該也可以。在作業系統新增環境變數如:

image.png
也可以在程式啟動時通過命令列傳參設定環境值。
但是這兩種我都感覺不方便,我們希望程式根據不同的環境釋出好以後,只需要直接執行就好,而不是需要進行額外的配置或傳參。

EnvironmentName 屬性

在專案的工程檔案中有EnvironmentName屬性,可以指定當前EnvironmentName值,新增如下程式碼
image.png
然後編譯後的,直接執行,就能夠讀取到appsettings.TEST.json配置檔案。
這配置不會覆蓋launchSettings.json中指定的環境值,但在影響釋出後的EnvironmentName值,從而可以改變實現釋出後預設的EnvironmentName值。
那這樣設定後,豈不是釋出後的EnvironmentName值只能是Test,如果要釋出其他環境還要每次釋出前修改這個值,那不是很麻煩嗎?
沒錯如果沒有點其他手段,那這真是多此一舉啊,請看下圖。
image.png
懂了吧,我們只需要多配置一個PublishProfile釋出檔案,指定不同的配置項,然後結合Condition條件來控制EnvironmentName
image.png
至此,完美實現根據不同環境選擇不同的釋出檔案,進行釋出專案,目標機器不需要做任何配置,直接執行就是我們想要的效果。
總結雖然ASP.NET和ASP.NETCore實現多環境的方式不同,但是最後釋出時我們可以做到一樣的效果,所有的配置都是一次性的,釋出時指定對應的PublishProfile即可。

相關文章