.netmsbuildazure-pipelinesxdt-transform

Web.config transformations + Azure CI/CD doesn't work


im trying to make Web.Config transformations work. I have got base Web.config:

... (irrelevant code)

<configuration>
    <connectionStrings>
        <add name="sampleConnStringName" connectionString="sampleConnString" providerName="System.Data.EntityClient" />
    </connectionStrings>

... (irrelevant code)

Then i have Web.Debug.config:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
    <connectionStrings>
      <add name="sampleConnStringName" connectionString="debugConnString" providerName="System.Data.EntityClient"
        xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
    </connectionStrings>
</configuration>

and Web.Release.config:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
    <connectionStrings>
      <add name="sampleConnStringName" connectionString="releaseConnString" providerName="System.Data.EntityClient"
        xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
    </connectionStrings>
</configuration>

Of course transformation is not working when i'm building my app locally, but unfortunately it's also not working while using Azure YAML pipeline.

Relevant YAML part:

variables:
      BuildPlatform: 'any cpu'
      BuildConfiguration: 'Release'

 ... (irrelevant code)

 task: VSBuild@1
        displayName: Build MyUi
        inputs:
         solution: "$(solution)"
         msbuildArgs: '/p:TransformConfigFile=true /p:DeployDefaultTarget=WebPublish /p:DeployOnBuild=true /p:WebPublishMethod=FileSystem /p:publishUrl="$(build.artifactStagingDirectory)\MyUi" /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactStagingDirectory)\MyUi"'
         platform: "$(buildPlatform)"
         configuration: "$(buildConfiguration)"

      - task: PublishBuildArtifacts@1
        displayName: Publishing MyUi to artifacts
        inputs:
          PathtoPublish: '$(Build.ArtifactStagingDirectory)\MyUi'
          ArtifactName: 'drop'
          publishLocation: 'Container'

Even on this step (there are other steps in this pipeline like using VM Azure Agent with multiple CopyFiles@2 tasks), in artficats i can see the web.config being.. totally different - it's not even the original Web.config, it contains connections string mixed from app.config files from other projects in this solution - no matter if i add web.debug.config and web.release.config, and change main web.config, the web.config published to artifacts remains the same.

At first i thought that the web.config might not be even copied, but in properties it's marked as "Copy always" so it's not that case.

Maybe someone had this problem before, and can share solution, or better approach for this problem?

Edit: Azure Pipeline log:

PreTransformWebConfig:
  Found The following for Config tranformation:
  Web.config, bin\Web.config
  Creating directory "D:\a\1\s\2. UIlayer\MyUi\obj\Release\TransformWebConfig\transformed\".
  Creating directory "D:\a\1\s\2. UIlayer\MyUi\obj\Release\TransformWebConfig\transformed\bin\".
  Copying Web.config to obj\Release\TransformWebConfig\original\Web.config.
  Copying D:\a\1\s\2. UIlayer\MyUi\Web.config to obj\Release\TransformWebConfig\original\bin\Web.config.
  Copying D:\a\1\s\2. UIlayer\MyUi\Web.Release.config to obj\Release\TransformWebConfig\assist\Web.config.
  Copying D:\a\1\s\2. UIlayer\MyUi\bin\Web.Release.config to obj\Release\TransformWebConfig\assist\bin\Web.config.
TransformWebConfigCore:
  Transforming Source File: D:\a\1\s\2. UIlayer\MyUi\Web.config
    Applying Transform File: D:\a\1\s\2. UIlayer\MyUi\Web.Release.config
    Output File: obj\Release\TransformWebConfig\transformed\Web.config
  Transformation succeeded
TransformWebConfigCore:
  Transforming Source File: D:\a\1\s\2. UIlayer\MyUi\Web.config
    Applying Transform File: D:\a\1\s\2. UIlayer\MyUi\bin\Web.Release.config
    Output File: obj\Release\TransformWebConfig\transformed\bin\Web.config
  Transformation succeeded
PostTransformWebConfig:
  Transformed Web.config using D:\a\1\s\2. UIlayer\MyUi\Web.Release.config into obj\Release\TransformWebConfig\transformed\Web.config.
  Transformed D:\a\1\s\2. UIlayer\MyUi\Web.config using D:\a\1\s\2. UIlayer\MyUi\bin\Web.Release.config into obj\Release\TransformWebConfig\transformed\bin\Web.config.

...


Copying obj\Release\TransformWebConfig\transformed\Web.config to obj\Release\Package\PackageTmp\Web.config.
  Copying obj\Release\TransformWebConfig\transformed\bin\Web.config to obj\Release\Package\PackageTmp\bin\Web.config.
  
...
  
  
  WebFileSystemPublish:
  Creating directory "D:\a\1\a\MyUi".
  Copying obj\Release\Package\PackageTmp\Web.config to D:\a\1\a\MyUi\Web.config.



AutoParameterizationWebConfigConnectionStringsCore:
  Transforming Source File: D:\a\1\s\2. UIlayer\MyUi\obj\Release\Package\PackageTmp\bin\Web.config
    Applying Transform File: <?xml version="1.0"?>
          <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
            <connectionStrings>
              <add
                connectionString="{% token='$(ReplacableToken_#(parameter)_#(tokennumber))' xpathlocator='name' parameter='$(name)-Web.config Connection String' description='$(name) Connection String used in web.config by the application to access the database.' defaultValue='$(connectionString)' tags='SqlConnectionString' %}"
                xdt:Transform="SetTokenizedAttributes(connectionString)" xdt:SupressWarnings="True" />
            </connectionStrings>
          </configuration>
    Output File: obj\Release\CSAutoParameterize\transformed\bin\Web.config
  Transformation succeeded
PostAutoParameterizationWebConfigConnectionStrings:
  Auto ConnectionString Transformed obj\Release\Package\PackageTmp\Web.config into obj\Release\CSAutoParameterize\transformed\Web.config.
  Auto ConnectionString Transformed obj\Release\Package\PackageTmp\bin\Web.config into obj\Release\CSAutoParameterize\transformed\bin\Web.config.

...

AutoParameterizationWebConfigConnectionStringsCore:
  Transforming Source File: D:\a\1\s\2. UIlayer\MyUi\obj\Release\Package\PackageTmp\Web.config
    Applying Transform File: <?xml version="1.0"?>
          <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
            <connectionStrings>
              <add
                connectionString="{% token='$(ReplacableToken_#(parameter)_#(tokennumber))' xpathlocator='name' parameter='$(name)-Web.config Connection String' description='$(name) Connection String used in web.config by the application to access the database.' defaultValue='$(connectionString)' tags='SqlConnectionString' %}"
                xdt:Transform="SetTokenizedAttributes(connectionString)" xdt:SupressWarnings="True" />
            </connectionStrings>
          </configuration>
    Output File: obj\Release\CSAutoParameterize\transformed\Web.config
  Transformation succeeded
  Transforming Source File: D:\a\1\s\2. UIlayer\MyUi\obj\Release\Package\PackageTmp\bin\Web.config
    Applying Transform File: <?xml version="1.0"?>
          <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
            <connectionStrings>
              <add
                connectionString="{% token='$(ReplacableToken_#(parameter)_#(tokennumber))' xpathlocator='name' parameter='$(name)-Web.config Connection String' description='$(name) Connection String used in web.config by the application to access the database.' defaultValue='$(connectionString)' tags='SqlConnectionString' %}"
                xdt:Transform="SetTokenizedAttributes(connectionString)" xdt:SupressWarnings="True" />
            </connectionStrings>
          </configuration>
    Output File: obj\Release\CSAutoParameterize\transformed\bin\Web.config
  Transformation succeeded

Solution

  • As per the VSBuild task log, after the config transform, it has another automatic parameterization of connection strings in the web.config file during the build. Please add /p:AutoParameterizationWebConfigConnectionStrings=False in msbuildArgs to skip it.

    I created an old .net framework MVC app, and the web.config is transfromed by the Web.release.config as expected:

    enter image description here

    My task below:

      - task: VSBuild@1
        displayName: Build solution
        inputs:
          solution: $(BuildParameters.solution)
          msbuildArgs: /p:DeployOnBuild=true /p:AutoParameterizationWebConfigConnectionStrings=False /p:WebPublishMethod=FileSystem /p:publishUrl="$(build.artifactStagingDirectory)\MyUi" /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactStagingDirectory)\MyUi"
          platform: $(BuildPlatform)
          configuration: $(BuildConfiguration)