其實我們在透過 dotnet publish 發行 ASP․NET Core 網站時,預設都會自動發佈一個 web.config 檔案,但是事實上這個檔案跟 Kestrel 完全沒關係,這個檔案主要是給 IIS 看的,當你想部署 ASP․NET Core 到 IIS 的時候,就一定需要這個檔案。今天這篇文章我就來說說,如何在執行 dotnet publish 命令的時候,自動調整 ASP․NET Core 部署到 IIS 的 web.config 內容。

預設的 Web.config 內容
預設的發行任務,搭配 -o DIR 可以將發行後的檔案輸出到指定路徑下:
dotnet publish -o dist
上述命令等同於加上了 -c Debug 組態設定,是一樣意思:
dotnet publish -c Debug -o dist
注意: -c Debug 與 -c DEBUG 到最後都會轉大寫,你用 C# 條件式編譯時,使用 #if Debug 是錯誤的寫法,用 #if DEBUG 才是正確的寫法!詳見 C# 前置處理器指示詞 文件。
其輸出路徑下的 web.config 內容長這樣:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <handlers>
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
      </handlers>
      <aspNetCore processPath="dotnet" arguments=".\api1.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
    </system.webServer>
  </location>
</configuration>
這個設定檔,其實缺少了一組重要的「環境變數」名為 ASPNETCORE_ENVIRONMENT,而該環境變數的預設值為 Production,這個變數決定了 ASP․NET Core 跑在什麼樣的環境下,不同的環境可以註冊不同的 Middleware 與程式邏輯,因此學習到環境的切換技巧非常重要,本文稍後會特別強調如何調整環境定義。
除此之外,你也可以發行 Release 組態,而這兩種組態的差別,主要影響的範圍是 C# 條件式編譯的結果!
dotnet publish -c Release -o dist
注意: -c Release 與 -c RELEASE 到最後都會轉大寫,你用 #if Release 是錯誤的寫法,用 #if RELEASE 才是正確的寫法!
發佈到測試環境(Development)
你可以在執行 dotnet publish 時,透過 -p:EnvironmentName=Development 明確指定「環境名稱」到發行的結果中:
dotnet publish -c Debug -p:EnvironmentName=Development
實際上會影響的地方,主要是輸出的 web.config 會自動內建環境變數的設定,非常方便!
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <handlers>
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
      </handlers>
      <aspNetCore processPath="dotnet" arguments=".\api1.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess">
        <environmentVariables>
          <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />
        </environmentVariables>
      </aspNetCore>
    </system.webServer>
  </location>
</configuration>
發佈到正式環境(Production)
相對的,你也可以在執行 dotnet publish 時,透過 -p:EnvironmentName=Production 明確指定 Production 這個「環境名稱」到發行的結果中:
dotnet publish -c Release -p:EnvironmentName=Production
以下是輸出的 web.config 內容,一樣內建包含了環境變數的設定!
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <handlers>
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
      </handlers>
      <aspNetCore processPath="dotnet" arguments=".\api1.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess">
        <environmentVariables>
          <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Production" />
        </environmentVariables>
      </aspNetCore>
    </system.webServer>
  </location>
</configuration>
發佈時不要發佈 web.config 檔案
由於我們很有可能對 web.config 進行調整,下次在部署時可能會蓋掉 web.config 的內容,針對這個問題,你只要在執行 dotnet publish 時加上 -p:IsTransformWebConfigDisabled=true 參數,即可停用 web.config 輸出,發行目錄中就不會有 web.config 這個檔案存在!👍
dotnet publish -c Release -p:IsTransformWebConfigDisabled=true
發佈時不要發佈 web.config 檔案但必要時透過參數指定輸出
除此之外,你也可以直接在 *.csproj 加入一個 IsTransformWebConfigDisabled Property 並設定為 true,就可以變更預設的輸出不要包含 web.config 檔案,我個人比較喜歡這樣的設定方式:
<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.4" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
  </ItemGroup>
</Project>
之後你輸入 dotnet publish -c Release 預設就不會輸出 web.config 檔案:
dotnet publish -c Release
不過你依然可以從 CLI 設定 -p:IsTransformWebConfigDisabled=false 參數,讓該次發行輸出 web.config 檔案:
dotnet publish -c Release -p:IsTransformWebConfigDisabled=false
如果要連同輸出環境名稱,就可以這樣執行:
dotnet publish -c Release -p:IsTransformWebConfigDisabled=false -p:EnvironmentName=Production
相關連結