dotnet / sdk

Core functionality needed to create .NET Core projects, that is shared between Visual Studio and CLI
https://dot.net/core
MIT License
2.71k stars 1.06k forks source link

Publish no longer merges custom web.config when upgraded SDK from 3.1.302 to 3.1.401 #14886

Open mcetkovsky opened 3 years ago

mcetkovsky commented 3 years ago

Reproduction steps

  1. Install .NET Core SDK 3.1.302 and 3.1.401.
  2. Create the following files:

PublishWebConfigBug.csproj

<Project Sdk="Microsoft.NET.Sdk.Web">

    <PropertyGroup>
        <TargetFramework>netcoreapp3.1</TargetFramework>
    </PropertyGroup>

    <ItemGroup>
        <Content Update="wwwroot\web.config" CopyToOutputDirectory="Always" CopyToPublishDirectory="Always" Link="%(Filename)%(Extension)" />
    </ItemGroup>

</Project>

global.json

{
  "sdk": {
    "version": "3.1.401"
  }
}

Program.cs

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

namespace PublishWebConfigBug
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args);
    }
}
  1. Run the following command:
dotnet publish PublishWebConfigBug.csproj --configuration Release
  1. Open the following file:

./bin/Release/netcoreapp3.1/publish/web.config

Actual Result

<?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=".\PublishWebConfigBug.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
    </system.webServer>
  </location>
</configuration>

Expected Result

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <defaultDocument>
      <files>
        <remove value="Default.asp" />
        <remove value="iisstart.htm" />
      </files>
    </defaultDocument>
    <handlers>
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
    </handlers>
    <aspNetCore processPath="dotnet" arguments=".\PublishWebConfigBug.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
  </system.webServer>
</configuration>

Additional notes

Using SDK up to 3.1.302 produces Expected Result's web.config while SDK 3.1.401 or above produces Actual Result's web.config - can be confirmed by specifying 3.1.302 instead of 3.1.401 in global.json.

It sounds like a breaking change in a patch version.

Our deployments are now broken because of this as rewrite rules etc. are not propagated into the final web.config. Should we provide custom web.config settings differently?

sfoslund commented 3 years ago

I'm not able to repro the expected result with an older version of 3.1 (I tried 3.1.200), does this only repro specifically with 3.1.302? If not, can you provide more information on how to repro the expected result?

mcetkovsky commented 3 years ago

@sfoslund I've just tried it in 3.1.200 and I do get the expected result.

This method of publishing web.config is in use since (at least) 10/2019 using several version of .NET Core 3.0 and 3.1. The last known deployment is from 07/2020, the first broken deployment was in 11/2020.

The following output is taken on macOS Big Sur, our build servers are running Windows 2019.

% dotnet --list-sdks
3.1.200 [/usr/local/share/dotnet/sdk]
3.1.301 [/usr/local/share/dotnet/sdk]
3.1.302 [/usr/local/share/dotnet/sdk]
3.1.401 [/usr/local/share/dotnet/sdk]
3.1.403 [/usr/local/share/dotnet/sdk]
3.1.404 [/usr/local/share/dotnet/sdk]
5.0.100 [/usr/local/share/dotnet/sdk]

% ls -R 
Program.cs                      PublishWebConfigBug.csproj      PublishWebConfigBug.sln         global.json                     wwwroot

./wwwroot:
web.config

% cat ./global.json 
{
  "sdk": {
    "version": "3.1.200"
  }
}%

% dotnet publish PublishWebConfigBug.csproj --configuration Release
Microsoft (R) Build Engine version 16.5.0+d4cbfca49 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restore completed in 91.97 ms for /[...]/PublishWebConfigBug.csproj.
  PublishWebConfigBug -> /[...]/bin/Release/netcoreapp3.1/PublishWebConfigBug.dll
  PublishWebConfigBug -> /[...]/bin/Release/netcoreapp3.1/publish/

% cat ./bin/Release/netcoreapp3.1/publish/web.config 
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <defaultDocument>
      <files>
        <remove value="Default.asp" />
        <remove value="iisstart.htm" />
      </files>
    </defaultDocument>
    <handlers>
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
    </handlers>
    <aspNetCore processPath="dotnet" arguments=".\PublishWebConfigBug.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
  </system.webServer>
</configuration>
<!--ProjectGuid: [...]-->%  
sfoslund commented 3 years ago

Can you provide a binlog of both situations?

mcetkovsky commented 3 years ago

Can you help me with building the right command please? I've checked the link but I still have no clue how to update or replace the dotnet publish command.

sfoslund commented 3 years ago

You can just add /bl to the end of the existing command

mcetkovsky commented 3 years ago

binlogs for 3.1.302 and 3.1.401 are in Archive.zip

mcetkovsky commented 3 years ago

The issue triggers only if the following line is present:

        <Content Update="wwwroot\web.config" CopyToOutputDirectory="Always" CopyToPublishDirectory="Always" Link="%(Filename)%(Extension)" />

If I move web.config into the project root and remove the line, the web.config is as Expected even on newer .NET Core SDKs.