How can I apply configuration transforms to EntLib

2019-04-15 04:04发布

问题:

I had a large Silverlight project with an unwieldy web.config, which used transforms against the web.debug.config, web.uat.config, and web.release.config files.

I've not separated out my EntLib configuration into EntLib.config, with matching EntLib.debug.config, EntLib.uat.config and EntLib.release.config files. I've edited the .csproj file and used DependentUpon so that the files are nested under EntLib.config. Now I'm trying to get VS2010 to apply the transforms when I use the Publish... menu option to publish the files straight to the test server.

I've been trying to apply this as shown below but it doesn't seem to work. I can see the transformed EntLib.config file in obj\$(Configuration)\TransformWebConfig\transformed but it isn't deployed. I've also tried using Project > Build Deployment Package which I've then run on another machine. Both leave me with EntLib.config in its original form plus each of the EntLib.($Configuration).config files alongside it. Should it work? Any help anyone can offer would be appreciated.

<PropertyGroup>
    <ConfigFileName>EntLib.config</ConfigFileName>
  </PropertyGroup>
  <PropertyGroup>
    <!-- This property is used to handle circular dependency between
    TransformWebConfig and our custom target TransformAppConfig   -->
    <FirstRun Condition="$(FirstRun) == ''">true</FirstRun>
  </PropertyGroup>
  <!-- This target will be called one time after a call to TransformWebConfig -->
  <Target Name="TransformAppConfig" AfterTargets="TransformWebConfig" Condition="$(FirstRun) == 'true'">
    <MSBuild Projects="$(MSBuildProjectFile)" Targets="TransformWebConfig" Properties="ProjectConfigFileName=$(ConfigFileName);&#xD;&#xA;                         Configuration=$(Configuration);                        &#xD;&#xA;                         FirstRun=false" />
  </Target>
  <!-- This target will be called one time before PreAutoParameterizationWebConfigConnectionStrings
       to add $(ConfigFileName) to autoparameterization step -->
  <Target Name="AddToAutoParameterizationStep" BeforeTargets="PreAutoParameterizationWebConfigConnectionStrings">
    <ItemGroup>
      <_WebConfigsToAutoParmeterizeCS Include="@(FilesForPackagingFromProject)" Condition="('%(FilesForPackagingFromProject.Filename)%(FilesForPackagingFromProject.Extension)'=='$(ConfigFileName)') And !%(FilesForPackagingFromProject.Exclude)">
        <TransformOriginalFile>$(AutoParameterizationWebConfigConnectionStringsLocation)\original\%(DestinationRelativePath)</TransformOriginalFile>
        <TransformOutputFile>$(AutoParameterizationWebConfigConnectionStringsLocation)\transformed\%(DestinationRelativePath)</TransformOutputFile>
        <TransformScope>$(_PackageTempDir)\%(DestinationRelativePath)</TransformScope>
      </_WebConfigsToAutoParmeterizeCS>
      <_WebConfigsToAutoParmeterizeCSOuputFiles Include="@(_WebConfigsToAutoParmeterizeCS->'%(TransformOutputFile)')">
      </_WebConfigsToAutoParmeterizeCSOuputFiles>
    </ItemGroup>
  </Target>

回答1:

I use T4 and TextTransform.exe to create different configs based on build configuration. You can take a look on my snippets for app.config, but the same technique can be applied for web.config.

1) Project structure

ProjectDir
  App_Config 
    Configuration.tt     // template for all configs
    Debug.App.tt         // settings for Debug
    Release.App.tt       // settings for Release
    ProductDeploy.App.tt // settings for deploy
  App.config             // autogenerated. Ignored in SVN
  project.csproj          

2) project.csproj modification allows to have up-to-date config for specified Platform/Configuration.

  <PropertyGroup>
    <T4Template>$(ProjectDir)\App_Config\$(Configuration).App.tt</T4Template>
    <T4CommonTemplate>$(ProjectDir)\App_Config\Configuration.tt</T4CommonTemplate>
    <T4Config>$(ProjectDir)\App.config</T4Config>
    <T4LastConfiguration>$(BaseIntermediateOutputPath)\$(Configuration).t4lastbuild</T4LastConfiguration>
  </PropertyGroup>
  <Target Name="BeforeBuild" DependsOnTargets="ExecuteT4Templates" />
  <Target Name="ExecuteT4Templates"     Inputs="$(T4Template);$(T4CommonTemplate);$(T4LastConfiguration)" Outputs="$(T4Config)">
    <MakeDir Directories="$(BaseIntermediateOutputPath)" Condition="!Exists('$(BaseIntermediateOutputPath)')" />
    <ItemGroup>
      <T4ConfigFlags Include="$(BaseIntermediateOutputPath)\*.t4lastbuild" />
    </ItemGroup>
    <Delete Files="@(T4ConfigFlags)" />
    <WriteLinesToFile File="$(T4LastConfiguration)" Lines="T4 Succeeded" Overwrite="true" />
    <Exec Command="TextTransform &quot;$(T4Template)&quot; -out &quot;$(T4Config)&quot;" WorkingDirectory="C:\Program Files\Common Files\microsoft shared\TextTemplating\1.2\" />
  </Target>
  <Target Name="AfterClean">
    <ItemGroup>
      <T4ConfigFlags Include="$(BaseIntermediateOutputPath)\*.t4lastbuild" />
    </ItemGroup>
    <Delete Files="@(T4ConfigFlags)" />
  </Target>

3) Configuration.tt sample

<#@ template language="C#"#>
<#@ output extension= ".config"#>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings>
        <add name = "NameSpace.Properties.Settings.SomeConnectionString"
         connectionString = "<#= this.SomeConnectionString #>"
         providerName     = "System.Data.SqlClient" />    
  </connectionStrings>

  <applicationSettings>
    <NameSpace.Properties.Settings>
            <setting name="DefAppSetting" serializeAs="String">
                <value><#= this.DefAppSetting #></value>
            </setting>          
        </NameSpace.Properties.Settings>    
  </applicationSettings>
</configuration>

<#+
  string SomeConnectionString = "default SomeConnectionString";
  string DefAppSetting = "some_value";
#>

4) Debug.App.tt sample

<#
  SomeConnectionString = "Data Source=.;Initial Catalog=SomeDB;Integrated Security=True";  
  DefAppSetting = "debug_some_value";  
#>
<#@ include file="Configuration.tt" #>


回答2:

I solved this using this article: Xml Document Transforms (XDT) for any XML file in your project by Vishal Joshi and posted the specifics here: How to apply transforms to EntLib.config.

My own solution followed Vishal's option to store his XDT targets file in the project so that it gets stored in source control and is available to everyone, rather than storing it locally on the machine.