Category Archives: Configuration

Transforming config files using SlowCheetah

It’s not unusual for our applications to require different configuration files (whether App.config or other) which might reflect different environments or build configurations. Under such circumstances I’ve tended to stick to using (good old) Nant to switch tokens in my configuration files as and when required.

An alternative to Nant or Cake etc. is Microsoft’s SlowCheetah, which allows us to create transformations within our configuration files, whether XML or JSON based as part of the build process within Visual Studio. These files will be named after the build configuration that you build your project with, i.e. Debug, Release etc.

To try this out, we first need to install SlowCheetah. So from Tools | Extensions and Updates, search for SlowCheetah and download it – you’ll need to restart Visual Studio to get it to installed.

Once installed we can right mouse click on the App.config and should see the option Add Transform.

Note: When we first add a transform Visual Studio will ask you to install the SlowCheetah NuGet package, select Yes when prompted.

Once you’ve executed Add Transform against the App.config you’ll find child nodes in solution explorer for App.Debug.config and App.Release.config (and any other build configurations you have).

If you right mouse click on either of these new config files, the context menu should show the option to Preview Transform. As the name suggests, this allows us to see what the transform will look like instead of having to build our solution to view the App.config within the bin folder.

Transforming .config files

In our simple implementation/example, we’ve got three App.config files now. The original App.config (which is ultimately what we’ll see in the bin folder as the exe.config) and a version of this file for Debug and Release builds.

What we need to do is add some configuration into the App.config as normal, so for example add the following

<appSettings>
   <add key="environment" value="NONE" />
</appSettings>

We can now add configuration to the Debug and Release config files to override this value. To save on duplicated config let’s concentrate on the App.Debug.config, so when we build using the Debug configuration SlowCheetah will transform our App.config with instructions from the App.Debug.config. Here’s an update to the App.Debug.config file

<appSettings>
   <add key="environment" value="DEBUG" 
      xdt:Transform="Replace" 
      xdt:Locator="Match(key)" />
</appSettings>

Note: the syntax for XML transformations is taken from XDT and for JSON from JDT.

As you can probably work out for yourself, we’re telling the transformation engine to replace the value for the given key. Without these two attributes no transformation takes place. Just adding configuration to this file, i.e. if we added another key/value solely to the App.Debug.config, will simply be ignored unless we tell the transformer what to do. For example if we wanted the App.Debug.config build to insert/add a new app settings key/value we can tell the transformer to do this using

<add key="url" 
   value="http://somewhere.com" 
   xdt:Transform="Insert"/>

Transformation syntax for XDT can be found here Transform Attribute Syntax.

Transform attributes include

  • Replace
  • Insert
  • InsertBefore
  • InsertAfter
  • Remove
  • RemoveAll
  • RemoveAttributes
  • SetAttributes

Transforming .json files

We may be using JSON files for configuration or support files (for example when creating .NET core applications or in any other type of application). SlowCheetah allows transformations on JSON as well using JDT.

Let’s add a JSON file to our test application, mine’s named Config.json and includes the following

{
  "appSettings" : {
     "environment" : "None" 
  }
}

Now in solution explorer within Visual Studio, right mouse click on Config.json and select Add Tranform. Again we’ll concentrate solely on the Config.Debug.json file that’s created as part of this process. Add the following to this file

{
  "appSettings" : {
    "@jdt.replace" : {
      "environment" :  "Debug" 
    } 
  }
}

As I’m sure you can see, we’re aiming to replace the value of the environment key to Debug (as we did with the .config previously). Obviously to see this happen and output to the relevant bin folder, select the Config.json (parent node) and set its property Copy to Output Directory to Copy if newer, now select each of the child nodes and switch those back to Do not copy as Visual Studio will set the child nodes to the same build action as the parent and we do not want/need these environment configurations in our output folder.

JDT includes the following verbs

References

SlowCheetah
SlowCheetah on GitHub

More custom configuration in the App.config (using IConfigurationSectionHandler)

In the previous post I outlined how to easily create custom configuration code for accessing section of the App.config file. In some situation you may want to take things a little further, so let’s now look at using the IConfigurationSectionHandler to create the same configuration section.

To review, let’s look at the configuration section we’re going to create

<configSections>
   <section name="FiltersSection" type="RvMonitor.FiltersSection, RvMonitor"/>
</configSections>

<FiltersSection>
   <Filters>
      <add type="Filters.ClassNameFilter, Filters" />
      <add type="Filters.ClassNameFilter, Filters" />
   </Filters>
</FiltersSection> 

So for this example, we’re not going to change this configuration and in fact we’ll keep the code which uses this configuration the same, so this will look like

var filtersSection = (FiltersSection)ConfigurationManager.GetSection("FiltersSection");

The first thing we need to do is create the FiltersSection class which will implement IConfigurationSectionHandler. This requires that we implement the Create method. Now you could return the filter collection from this code instead of the FiltersSection, but I wanted to show how the two techniques would look, code-wise, for the same functionality. So in our Create method we’ll return the FiltersSection, as follows (the code below is the full implementation of the FilterSection, we’ll look at each bit of interest in a minute)

Note: I will not deal with error handling within this code so I can keep it to a minimum

public class FiltersSection : IConfigurationSectionHandler
{
   public FiltersSection()
   {
      Filters = new List<FilterType>();
   }

   public object Create(object parent, object configContext, XmlNode section)
   {
      var serializer = new XmlSerializer(typeof(FilterType));

      foreach (XmlNode node in section.ChildNodes)
      {
         if (node.Name == "Filters")
         {
            foreach (XmlNode filterNode in node.ChildNodes)
            {
               var reader = new XmlNodeReader(filterNode);
               Filters.Add((FilterType)serializer.Deserialize(reader));
            }
         }
      }
      return this;
   }

   public IList<FilterType> Filters { get; private set; }
}

So the obvious (boring bits) are we added a Filters property to the FiltersSection and instantiated it within the constructor, but the interesting stuff is within the Create method.

First off, as noted earlier, I wanted to mimic the behaviour of a previous post. So we return this

Easy custom configuration section in the App.config

There’s a couple of ways to handle configuration sections within the App.config file. The simplest (in my opinion at least) is by inheriting from the ConfigurationSection, ConfigurationElement and so on. The alternative would be to implement the IConfigurationSectionHandler, but that’s for another post.

So here’s a simple scenario…

I have a simple Tibco RV monitor application. My own implementation, of sorts of TIB’s tibrvlisten.exe, but with the ability to log and filter messages etc. So I want to create a simply configuration section for supplying a list of the filters to plugin to the application (similar to the way some IoC libraries work).

Here’s a sample of the App.config that I want

<configSections>
   <section name="FiltersSection" type="RvMonitor.FiltersSection, RvMonitor"/>
</configSections>

<FiltersSection>
   <Filters>
      <add type="Filters.ClassNameFilter, Filters" />
      <add type="Filters.ClassNameFilter, Filters" />
   </Filters>
</FiltersSection> 

Let’s start at outside and work inwards.

So quite obviously (from the configSections) we’re going to require a FiltersSection object. We need to derive our FiltersSection from the system.Configuration.ConfigurationSection class. This class will then have a ConfigurationProperty named Filters, which translates to our Filters element. This will be a collection or more specifically a type derived from the ConfigurationElementCollection. Let’s take a look at the code for the FiltersSection first

public class FiltersSection : ConfigurationSection
{
   [ConfigurationProperty("Filters")]
   [ConfigurationCollection(typeof(FiltersCollection),
      AddItemName = "add", 
      ClearItemsName = "clear", 
      RemoveItemName = "remove")]
   public FiltersCollection Filters
   {
      get { return (FiltersCollection)this["Filters"]; }
   }
}

Before we look at the very simple implementation of FiltersCollection let’s review this code.

The ConfigurationProperty simply defines the name of the element which our collection resides within. The ConfigurationCollection attribute then tells the ConfigurationManager the type of the collection and defines the elements to add, clear and remove items. We’re actually only interested in adding filters, after all you can just remove them from the App.config if you want to clear or remove items. The “add” name can be changed and relates to the add elements within the Filters element of the configuration, i.e.

<add type="Filters.ClassNameFilter, Filters" />

So let’s create a simply ConfigurationCollection

public class FiltersCollection : ConfigurationElementCollection
{
   protected override ConfigurationElement CreateNewElement()
   {
      return new FilterType();
   }

   protected override object GetElementKey(ConfigurationElement element)
   {
      return element;
   }
}

I’ve shown the bare minimum required to implement a ConfigurationElementCollection. Obviously we need some way to create instances of our element type (i.e. that type that our “add” element creates). Here we create a FilterType via the CreateNewElement method. I’ve not bothered creating an element key, so I’m just returning element from GetElementKey, but you might prefer to use something like

protected override object GetElementKey(ConfigurationElement element)
{
   return ((FilterType)element).TypeName;
}

Finally let’s look at the extremely simple FilterType which derives from the ConfigurationElement type.

public class FilterType : ConfigurationElement
{
   [ConfigurationProperty("type", IsRequired = true)]
   public string TypeName
   {
      get { return (string) this["type"]; }
      set { this["type"] = value; }
   }
}

Notice how in this class and the FiltersSection class we use the built in Hashtable to store our actual property data.

And that’s about it, oh, except how to use the code within our app. Here’s the code

var filtersSection = (FiltersSection)ConfigurationManager.GetSection("FiltersSection");

and there we have it, pretty simple.