How to merge .net custom config sections for different environments

145 views Asked by At

Our .net build system uses Enterprise Library 4.1 to replace default web.config settings by calling MergeConfiguration.exe and supplying the original web.config and the delta files for each environment (such as Test and Production) so that the resulting installer packages all environments' specific web.config and installs the correct version based on environment.

This works well for sections known to Enterprise Library, such as the appSettings section. However, we also have some custom sections which I would like to differentiate between environments, such as the following.

For Test

<RoutingSection type="AbcSystem.RoutingSection, AbcSystem"> <Route Source="1" Destination="2" /> ... </RoutingSection>

For Production

<RoutingSection type="AbcSystem.RoutingSection, AbcSystem"> <Route Source="1" Destination="3" /> ... </RoutingSection>

Ideally the whole custom section is specified in delta files, and during build, replaces its default version from the original web.config.

Without implementing our own delta merge tool, I have not found a solution. Believing this is a common need for software development, I am seeking for a solution, ideally one that does not involve too many changes to the aforementioned process. It does not have to be Enterprise Library. Thanks in advance.

2

There are 2 answers

1
Xeon On BEST ANSWER

I eventually used SlowCheetah, producing a transformed config file for each environment. It is also TFS build friendly, not requiring changes to the build process. I've also moved our merges previously done using Enterprise Library 4.1 to SlowCheetah, together with the custom sections.

1
granadaCoder On

The msbuild below will copy your original file and update the value from 2 to 3.

You will have to install MSBuildCommunityTasks and get the "import project" file name right....but the logic below will work for you.

<?xml version="1.0" encoding="utf-8"?>
<Project  ToolsVersion="4.0"  xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="AllTargetsWrapped">

    <!--
  <UsingTask AssemblyFile="$(ProgramFiles)\MSBuild\MSBuild.Community.Tasks.dll" TaskName="Version"/>
  -->
    <Import Project="$(MSBuildExtensionsPath32)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />



    <PropertyGroup>
        <!-- Always declare some kind of "base directory" and then work off of that in the majority of cases  -->
        <WorkingCheckout>.</WorkingCheckout>
    </PropertyGroup>

    <PropertyGroup>
        <DestinationForProductionValue>3</DestinationForProductionValue>
    </PropertyGroup>

    <Target Name="AllTargetsWrapped">
        <CallTarget Targets="CopyItTarget" />
        <CallTarget Targets="WriteXmlPeekValue" />
    </Target>   


    <Target Name="CopyItTarget">
        <Copy SourceFiles="$(WorkingCheckout)\Parameters.xml" DestinationFiles="$(WorkingCheckout)\Parameters_PRODUCTION.xml"/>     
        <Error Condition="!Exists('$(WorkingCheckout)\Parameters_PRODUCTION.xml')" Text="No Copy Is Bad And Sad" />
    </Target>


    <Target Name="WriteXmlPeekValue"  Condition=" '$(DestinationForProductionValue)' != '' ">
        <XmlPoke 
    XmlInputPath="$(WorkingCheckout)\Parameters_PRODUCTION.xml"
            Query="/root/RoutingSection/Route/@Destination"
    Value="$(DestinationForProductionValue)" />
    </Target>   




</Project>