<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Richard&#039;s Random Ramblings &#187; .NET Core</title>
	<atom:link href="http://blog.rjcox.co.uk/category/dev/net-core/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.rjcox.co.uk</link>
	<description>Whatever I think is interesting... mostly about computing but not always</description>
	<lastBuildDate>Tue, 22 Jun 2010 13:29:49 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Custom Configuration for .NET (Part 5): Backgrounder on Configuration &#8220;Inheritance&#8221;</title>
		<link>http://blog.rjcox.co.uk/2010/06/22/custom-configuration-5/</link>
		<comments>http://blog.rjcox.co.uk/2010/06/22/custom-configuration-5/#comments</comments>
		<pubDate>Tue, 22 Jun 2010 11:21:15 +0000</pubDate>
		<dc:creator>Richard</dc:creator>
				<category><![CDATA[.NET Core]]></category>

		<guid isPermaLink="false">http://blog.rjcox.co.uk/?p=145</guid>
		<description><![CDATA[Configuration Inheritance: There Are Multiple Configuration Files

Introduction

  Previous Parts of This Series.


  Note, the contents of the post covers non-ASP.NET applications. ASP.NET uses its own
  approach to configuration inheritance, and this article already contains
  more than enough information.


  Also note, I call this configuration inheritance because it
  expresses the [...]]]></description>
			<content:encoded><![CDATA[<h2>Configuration Inheritance: There Are Multiple Configuration Files</h2>

<h3>Introduction</h3>
<p>
  <a href='#prev-parts'>Previous Parts of This Series</a>.
</p>
<p>
  <em>Note</em>, the contents of the post covers non-ASP.NET applications. ASP.NET uses its own
  approach to configuration inheritance, and this article already contains
  more than enough information.
</p>
<p>
  <em>Also note</em>, I call this configuration <em>inheritance</em> because it
  expresses the idea of one thing overriding another. Given the limited conceptual
  documentation about .NET&rsquo;s configuration system I don&rsquo;t think there is
  an official term. Until there is I will stick with &ldquo;inheritance&rdquo;.
</p>
<p>
  When one uses the .NET configuration APIs to load settings into an application
  there is a rich structure supporting not just the kind of data that can be held,
  but also the scope of that data. Different applications can share data at the
  machine level, different AppDomains in the same process can have different
  configuration, and users can have their own settings either in the roaming part of
  their profile or purely local, or both.
</p>
<p>
  Where this data is stored, and what influences where is the subject of this
  posting, but on the way there is a little coverage of how to get it and
  manage it but mostly that will be for the future.
</p>

<h3>The Four Levels</h3>
<p>
  For non-ASP.NET there are four files, with each able&mdash;if the
  section allows it&mdash;to override the previous level. Some times of
  collection can also be modified by subsequence levels: clearing
  the collection, adding or removing members. The four levels are
</p>
<ol>
  <li>Machine</li>
  <li>Application</li>
  <li>User Roaming</li>
  <li>User Local</li>
</ol>

<h4>The Machine Configuration Level</h4>
<p>
  This is the global file, normally stored in
  <code>%SystemRoot%\Microsoft.NET\Framework64\<em>&lsaquo;Version&rsaquo;</em>\Config\machine.config</code>
  for 64bit .NET or
  <code>%SystemRoot%\Microsoft.NET\Framework\<em>&lsaquo;Version&rsaquo;</em>\Config\machine.config</code>
  for 32bit. Where <code>&lsaquo;Version&rsaquo;</code> is the full version, e.g. <code>v4.0.30319</code>
  for .NET 4.
</p>
<p>
  It is instructive to read through this file&mdash;if you have enabled local active content in
  Internet Explorer the ability to collapse elements makes this easier&mdash;because you will
  see all the standard sections and section groups defined with the classes that implement them.
  For instance <code>&lt;appSettings&gt;</code> is implemented by
  <code>System.Configuration.AppSettingsSection</code> in assembly System.Configuration. It
  is also in the <code>&lt;connectionStrings&gt;</code> section at the machine level that
  connection &ldquo;LocalSqlServer&rdquo; is defined to be SQL Express using data file
  <code>&hellip;\App_Data\aspnetdb.mdf</code> which is then used as the store for
  ASP.NET profiles in their default configuration. (ASP.NET also has a global configuration
  &ldquo;web.config&rdquo; in the same folder with yet more global settings.)
</p>
<p>
  As this file is read, by the configuration system, first any of the other levels can
  override it, unless the section
  is defined with <code>allowDefinition</code> or <code>allowExeDefinition</code> attribute
  is set to &ldquo;MachineOnly&rdquo; to ensure it can only be used at the machine level.
</p>

<h4>The Application Level</h4>
<p>
  This is the most familiar level, creating a file called &ldquo;app.config&rdquo; in
  a Visual Studio project will create a file
  &ldquo;<em>&lsaquo;assembly-name&rsaquo;</em>.config&rdquo;
  in the project output directory.
</p>

<h4>User Roaming and Local Levels</h4>
<p>
  If you set things up correctly, per user files can also be used. The roaming
  file will be part of the user&rsquo;s roaming profile, shared across machines if
  roaming is enabled. The local file will stay local. But you can override
  the filenames (see <a href='#define-own'>below</a>) and as the
  content of a user&rsquo;s roaming profile is based
  on a set of configurable folders, these names are strictly speaking indicative rather
  than absolute.
</p>
<p>
  User levels are most useful when the ability to save configuration content
  is enabled. Rather than storing user settings and options in the registry
  use these configuration files.
</p>
<p>
  The only problem with these files is the default naming, it is designed to
  ensure different versions of the same thing running side by side have
  separate configuration. If the location, assembly version or signing key
  changes then the filenames will be changed and any previous content (e.g.
  from before an upgrade) will be lost. This is bad news. The good news is
  that it is easy to specify your own filenames&mdash;and I would suggest
  doing that in most cases.
</p>

<h3>Using The User Levels</h3>
<p>
  If you just use the static properties of <code>ConfigurationManager</code> (or
  one of the other configuration entry points) then machine and application
  configuration files are included, but user files are not.
</p>
<p>
  To access either user-roaming, or user-roaming and user-local levels (you cannot
  use the local level without the roaming level&mdash;the roaming level could be left empty)
  one just uses one of the
  static <code>ConfigurationManager</code> methods that take a
  <code>ConfigurationUserLevel</code> parameter. The <code>ConfigurationUserLevel</code>
  enumeration allows selection of no user levels: <code>ConfigurationUserLevel.None</code>,
  just roaming: <code>ConfigurationUserLevel.PerUserRaoming</code>, or
  all levels: <code>ConfigurationUserLevel.PerUserRaomingAndLocal</code>.
</p>
<p>
  If the configuration is opened with the
  <code>ConfigurationManager.OpenExeConfiguration</code>
  method then the default filenames, created by the configuration system, are
  used. Alternately using <code>ConfigurationManager.OpenMappedExeConfiguration</code>
  allows the filenames to be specified (more on this below, after covering the default
  filenames).
</p>

<h3>What Are The Default Filenames?</h3>
<p>
  Disclaimer: none of this, as far as I can determine, is formally documented. Treat
  this information as subject to change in a future .NET version.
</p>

<h4>Default Filenames For The Default AppDomain of a Unsigned Executable</h4>
<p>
  This is the simplest, and likely starting, case. The application configuration
  is the starting assembly&rsquo;s path with &ldquo;.config&rdquo; appended.
  The user files will be:
</p>
<pre>
  %USERPROFILE%\<em>&lsaquo;folder&rsaquo;</em>\<em>&lsaquo;companyName&rsaquo;</em>\<em>&lsaquo;AssemblyBase&rsaquo;</em>_Url_<em>&lsaquo;hash&rsaquo;</em>\<em>&lsaquo;version&rsaquo;</em>\user.config
</pre>
<p>
  where
</p>
<ul style=''>
  <li>folder: Is either &ldquo;Roaming&rdquo; or &ldquo;Local&rdquo; depending on the level.</li>
  <li>
    companyName: Is the value of the <code>AssemblyCompanyAttribute</code> if
    set. If not then the value of the <code>AssemblyProductAttribute</code>.
    If neither is set then this path fragment is not included (one less
    directory in the path).
  </li>
  <li>
    AssemblyBase: is the first part of the assembly&rsquo;s filename (including the
    first period and two further characters).
  </li>
  <li>
    hash: is an alphanumeric string created by hashing the full path of the assembly
    in some implementation determined way.
  </li>
  <li>version: is the value of the <code>AssemblyVersionAttrinbute</code>.</li>
</ul>

<h4>With Code Signing</h4>
<p>
  If the assembly is signed then there is a small change. Rather than
  <code><em>&lsaquo;AssemblyBase&rsaquo;</em>_Url_<em>&lsaquo;hash&rsaquo;</em></code>
  we have
  <code><em>&lsaquo;AssemblyBase&rsaquo;</em>_StrongName_<em>&lsaquo;hash&rsaquo;</em></code>
  with the hash being based on the signing key (the rest of the path
  is the same). This means by signing the assembly
  the location of the user configuration files becomes independent of the location of
  the assembly. If you want <code>xcopy</code> deployment then signing would
  seem to be a good idea to allow the user to relocate the application while
  preserving their configuration.
</p>

<h4>With Other AppDomains</h4>
<p>
  If the configuration is loaded from a different AppDomain the machine and
  application configuration files remain the same. However the user levels file names change.
  In the above path <em>AssemblyBase</em> is replaced by the AppDomain name.
  Another case of trying to ensure uniqueness.
</p>
<p>
  One of the options on creating an AppDomain is to specify a different configuration
  file:
</p>
<pre>var adConfigPath = Path.GetDirectoryName(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
adConfigPath = Path.Combine(adConfigPath, "AppDomain.config");
var adSetup = new AppDomainSetup {
  ConfigurationFile = adConfigPath
};
otherDomain = AppDomain.CreateDomain("WithDifferentConfig", null, adSetup);</pre>
<p>
  In this case replacing the <code><em>AssemblyName</em>.config</code> with
  <code>AppDomain.config</code>. This results in the assembly level configuration
  file being the filename specified, but no other levels are changed. Specifically
  the user level filenames remain the same whatever application level configuration
  is specified.
</p>
<p>
  <em>Note</em>, if you don&rsquo;t give an AppDomain a name on creation, .NET will:
  there are no unnamed AppDomains.
</p>

<h3 id='define-own'>Defining You Own Filenames</h3>
<p>
  As noted above the default naming is not ideal (if you want to be
  able to revise the application) except in being confident of its uniqueness.
  You can however define all the filenames, except at machine level, yourself.
</p>
<p>
  To specify your own filenames you need to specify all the levels you are going
  to use, except the machine level. This includes the application level (to use the
  default just use <code>AppDomain.CurrentDomain.SetupInformation.ConfigurationFile</code>
  (this seems to be always populated whether not specified on AppDomain creation or
  in the default AppDomain) or <code>Assembly.GetEntryAssembly().Location + ".config"</code>.
</p>
<p>
  The real benefit is being able to specify you own path, to be independent of
  assembly/AppDomain name, assembly version, signing key and assembly location. Just
  construct the path you need, and remember with a new version you need to
  ensure that structural changes are either backwards compatible, or you include
  conversion code. Something like:
</p>
<pre>private static string GetProfileConfigPath(Assembly targetAssembly, Environment.SpecialFolder pathId) {
  var profile = Environment.GetFolderPath(pathId,
                                          Environment.SpecialFolderOption.None);
  var company = targetAssembly.GetAttribute&lt;AssemblyCompanyAttribute&gt;().Company;
  if (String.IsNullOrWhiteSpace(company)) {
    throw new InvalidOperationException("AssemblyCompanyAttribute must be set");
  }
  var configPath = Path.Combine(profile, company);
  configPath = Path.Combine(configPath, targetAssembly.GetName().Name);
  configPath = Path.Combine(configPath, "user.config");
  return configPath;
}</pre>
<p>
  This can be called with each of <code>Environment.SpecialFolder.ApplicationData</code>
  and <code>Environment.SpecialFolder.LocalApplicationData</code> to get the current
  users roaming and local profile root folders (respectively). (The <code>GetAttribute&lt;T&gt;()</code>
  method is a helper extension method over <code>Assembly</code> I have which gets
  the single instance of attribute <code>T</code> from the assembly.) Normally this would
  be passed the entry assembly, but for an extension could be passed the extension&lsquo;s
  assembly to keep configuration separate (and thus avoid conflicts) from the containing
  application.
</p>
<p>
  Once you have the filenames you want to use, populate an instance of
  <code>ExeConfigurationFileMap</code> and pass to
  <code>ConfigurationManager.OpenMappedExeConfiguration</code> to get
  a <code>Configuration</code> instance, which is used in exactly the
  same way as an instance obtained any other way.
</p>


<h3>Discovering the Names Being Used At Runtime</h3>
<p>
  There are two approaches: defined and laborious, or using reflection to
  peer inside the <code>Configuration</code> instance. The safe method
  is based on <code>Configuration.FilePath</code> being the path
  of the lowest level of configuration in use. So open with different
  <code>ConfigurationUserLevel</code> values and get each path in turn.
</p>
<p>
  The reflection method relies on <code>Configuration</code> having
  private member <code>_configRecord</code> of private type
  <code>System.Configuration.MgmtConfigurationRecord</code>. This
  is a linked list of <code>MgmtConfigurationRecord</code> instances, one
  per level. Each has a <code>_configName</code> field which gives the
  level as a string (&ldquo;MACHINE&rdquo;, &ldquo;EXE&rdquo;, &hellip;) giving
  the level, and a <code>ConfigurationFilePath</code> property with the path.
  Given an instance of <code>Configuration</code> and a few helpers a
  populated <code>ExeConfigurationFileMap</code> can be returned.
</p>

<h3>Reference</h3>
<p>
  In the posting:
  <a href='http://blogs.msdn.com/b/rprabhu/archive/2005/06/29/433979.aspx'>&ldquo;Client Settings FAQ&rdquo;</a>
  Raghavendra Prabhu covers some details of the user-roaming and user-local configuration levels.
  Including that the hash following the <code>_Url_</code> or <code>_StrongName_</code>
  is based on the evidence&mdash;i.e. of the URL or signing key.
</p>


<h3 id='prev-parts'>Previous Part of This Series on .NET Custom Configuration</h3>
<ol>
  <li><a href='/2010/05/17/custom-configuration-1/'>Demonstrating Custom Configuration Sections for .NET</a></li>
  <li><a href='/2010/05/21/custom-configuration-2/'>Demonstrating Custom Configuration for .NET (Part 2): Custom Elements</a></li>
  <li><a href='/2010/05/23/custom-configuration-3/'>Demonstrating Custom Configuration for .NET (Part 3): Validation</a></li>
  <li><a href='/2010/05/25/custom-configuration-4/'>Custom Configuration for .NET (Part 4): Backgrounder on Configuration Sections</a></li>
</ol>]]></content:encoded>
			<wfw:commentRss>http://blog.rjcox.co.uk/2010/06/22/custom-configuration-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Custom Configuration for .NET (Part 4): Backgrounder on Configuration Sections</title>
		<link>http://blog.rjcox.co.uk/2010/05/25/custom-configuration-4/</link>
		<comments>http://blog.rjcox.co.uk/2010/05/25/custom-configuration-4/#comments</comments>
		<pubDate>Tue, 25 May 2010 15:17:03 +0000</pubDate>
		<dc:creator>Richard</dc:creator>
				<category><![CDATA[.NET Core]]></category>

		<guid isPermaLink="false">http://blog.rjcox.co.uk/?p=141</guid>
		<description><![CDATA[Configuration Sections

  Updated 2010-06-22: Added link to part 5.


Introduction

  Previous Parts of This Series.


  There are two remaining approaches to providing structure that I have not yet
  covered: collections of elements and section groups. Element collections will
  be a topic for several future posts as there are a number of [...]]]></description>
			<content:encoded><![CDATA[<h2>Configuration Sections</h2>
<p>
  Updated 2010-06-22: Added link to part 5.
</p>

<h3>Introduction</h3>
<p>
  <a href='#prev-parts'>Previous Parts of This Series</a>.
</p>
<p>
  There are two remaining approaches to providing structure that I have not yet
  covered: collections of elements and section groups. Element collections will
  be a topic for several future posts as there are a number of different approaches
  to creating element collections, and two of them make little sense without
  first covering configuration inheritance
  (<a href='/2010/06/22/custom-configuration-5/'>see part 5</a>).
</p>

<p>
  Section groups are much simpler, and mostly a matter of declaring them.
</p>

<h3>Creating Section Groups</h3>
<p>
  When custom sections are declared using the <code>&lt;configSections&gt;</code>
  element of a configuration file, one can declare both sections (with the
  <code>&lt;sections&gt;</code> element, using attributes to define the associated
  custom type and its name) and section groups.
</p>
<p>
  To define a section group use the&mdash;unsurprisingly&mdash;<code>&lt;sectionsGroup&gt;</code>
  element. This needs a name and a type. Often the type will be
  <code>System.Configuration.ConfigurationSectionGroup</code> which adds no behaviour
  (but one can customise this, more below) and just allows programmatic access to
  its child sections and section groups (there is no specified limit to
  the depth of structure you can define&mdash;but don&rsquo;t go overboard with
  deep structures which will become increasingly hard to understand and maintain).
</p>
<p>
  For instance:
</p>
<pre>   &lt;configuration&gt;
    &lt;configSections&gt;
    &lt;sectionGroup name="userSettings"
          type="System.Configuration.ConfigurationSectionGroup, System.Configuration, Version=4.0.0.0,
                                                                Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"&gt;
      &lt;section name="recentFiles"
           type="CustomConfiguration.RecentFilesConfigurationSection, MyAssembly"/&gt;
    &lt;/sectionGroup&gt;
    &lt;/configSections&gt;

    &lt;userSettings&gt;
    &lt;recentFiles showFiles="5" removeNoneExistant="true"/&gt;
    &lt;/userSettings&gt;

  &lt;/configuration&gt;
</pre>
<p>
  Which defines a <code>userSettings</code> element to act as a container for (presumably)
  multiple sections describing many aspects of user behaviour.
</p>
<p>
  Note, replace the strong name for <code>System.Configuration</code> with
  &ldquo;<code>System.Configuration.ConfigurationSectionGroup, System.Configuration,
  Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</code>&rdquo;
  for .NET versions 2, 3 and 3.5.
</p>

<h3>Reading Section Groups and Contained Sections</h3>
<p>
  In previous parts of this series the application code used
  <code>Configuration.GetSection(&lsaquo;<em>name</em>&rsaquo;)</code> to get
  to its custom section (and the instance of <code>Configuration</code> was obtained
  with <code>ConfigurationManager.OpenExeConfiguration</code>).
  This works for configuration sections that are immediate children of the root
  <code>&lt;configuration&gt;</code> node.
</p>
</p>
  To get a section defined with a group simple get the group, and open the
  section from within that group. For instance, based on the above sample
  configuration:
<p>
<pre>var config = ConfigurationManager.OpenExeConfiguration(&hellip;);
var userSettingsGroup = config.GetSectionGroup("userSettings");
var recentFiles = (RecentFilesConfigurationSection) userSettingsGroup.GetSection("recentFiles");
</pre>
<p>
  <code>GetSectionGroup</code> returns a <code>ConfigurationSectionGroup</code> instance
  which has <code>GetSection</code> and <code>GetSectionGroup</code> methods as
  <code>Configuration</code> has.
</p>

<h4>Configuration Section and Group Collection Properties</h4>
<p>
  You might notice that the <code>Configuration</code> and
  <code>ConfigurationSectionGroup</code> also have properties
  <code>Sections</code> and <code>SectionGroups</code> which
  can be indexed by name. These give another approach to getting
  a section or section group:
</p>
<pre>  var myConfig = (MyConfigurationSection)config.GetSection("mine");
  var myConfig2 = (MyConfigurationSection)config.Sections["mine"];
</pre>
<p>
  are completely equivalent.
</p>

<h4>Custom Section Group Types</h4>
<p>
  It is also possible to create your own custom configuration section
  group by deriving from <code>ConfigurationSectionGroup</code>, and
  a number of .NET Framework types do this. E.g.
  <code>System.Xml.Serialization.Configuration.SerializationSectionGroup</code>
  defined in the <code>System.Xml</code> assembly, which adds properties
  to type safely access contained sections (i.e. the properties
  contain the access into the <code>Sections</code> collection
  and cast the results to the correct type).
</p>

<h3 id='prev-parts'>Previous Part of This Series on .NET Custom Configuration</h3>
<ol>
  <li><a href='/2010/05/17/custom-configuration-1/'>Demonstrating Custom Configuration Sections for .NET</a></li>
  <li><a href='/2010/05/21/custom-configuration-2/'>Demonstrating Custom Configuration for .NET (Part 2): Custom Elements</a></li>
  <li><a href='/2010/05/23/custom-configuration-3/'>Demonstrating Custom Configuration for .NET (Part 3): Validation</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.rjcox.co.uk/2010/05/25/custom-configuration-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Demonstrating Custom Configuration for .NET (Part&#160;3): Validation</title>
		<link>http://blog.rjcox.co.uk/2010/05/23/custom-configuration-3/</link>
		<comments>http://blog.rjcox.co.uk/2010/05/23/custom-configuration-3/#comments</comments>
		<pubDate>Sun, 23 May 2010 22:39:32 +0000</pubDate>
		<dc:creator>Richard</dc:creator>
				<category><![CDATA[.NET Core]]></category>

		<guid isPermaLink="false">http://blog.rjcox.co.uk/?p=137</guid>
		<description><![CDATA[Validating Values

Introduction

  Previous Parts of This Series.



  Parts 1 and
  2 added structure and
  data, but this is often not enough, one needs valid data&#8212;the
  domain of the data for your configuration being narrower than the
  domain of the underlying type of the parsed values. Hence the need to [...]]]></description>
			<content:encoded><![CDATA[<h2>Validating Values</h2>

<h3>Introduction</h3>
<p>
  <a href='#prev-parts'>Previous Parts of This Series</a>.
</p>

<p>
  Parts <a href='/2010/05/17/custom-configuration-1/'>1</a> and
  <a href='/2010/05/21/custom-configuration-2/'>2</a> added structure and
  data, but this is often not enough, one needs <em>valid</em> data&mdash;the
  domain of the data for your configuration being narrower than the
  domain of the underlying type of the parsed values. Hence the need to extend the custom
  types representing the structure with more types and attributes to limit the
  ranges of those values.
</p>

<h3>Value Validation</h3>
<p>
  Checking single values is the easiest part, albeit needing two custom types
  to be defined for each distinct kind of validation, but at least each case
  can be parameterised (i.e. if you need to check a date range, you only
  need two types, not four).
</p>

<h4>First: The Validator</h4>
<p>
  The first type is derived from <code>System.Configuration.ConfigurationValidatorBase</code>.
  This will actually do the validation in two steps:
</p>
<ol>
  <li>
    Overriding <code>CanValidate</code> to confirm that the type can be validated.
    Return <code>true</code> to indicate you can, otherwise validation will fail.
    This override is usually used to confirm the type of the value matches the
    expectations of the next method.
  </li>
  <li>
    Override <code>Validate</code> to perform the validation. To indicate failure
    throw an exception (which will be wrapped by the configuration runtime, into
    a <code>ConfigurationErrorsException</code>.
  </li>
</ol>
<p>
  <em>NB.</em> the validation needs to handle the default (before the configuration
  content is parsed) value. E.g. a </code>DateTime</code> value will be initially
  validated with a value of <code>DateTime.MinValue</code> before being called
  again with the value read from the configuration file. (For types which can
  be used with code attributes&mdash;see &sect;17.1.3 of the C# specification,
  the default value is an optional parameter for the <code>ConfigurastionProperty</code>
  attribute. For other types, the code attribute based declaration of configuration
  values can be replaced with a more programmatic one, which I should cover later
  in this series.)
</p>
<p>
  For instance to check that a <code>DateTime</code> value has a minimum year the
  following validation code will work (note the check to allow <code>MinValue</code>):
</p>
<pre>public class DateTimeValidator : ConfigurationValidatorBase {
    private DateTime lowerLimit;

    internal DateTimeValidator(DateTime lowerLimit) {
      this.lowerLimit = lowerLimit;
    }

    public override bool CanValidate(Type type) {
      return type.Equals(typeof(DateTime));
    }

    public override void Validate(object value) {
      Trace.Assert(value.GetType().Equals(typeof(DateTime)));
      DateTime val = (DateTime)value;

      // MinValue is used as a placeholder before the actual value is set
      if (val &lt; lowerLimit && val != DateTime.MinValue) {
        throw new ArgumentException("Invalid DateTime value in configuration");
      }
    }
  }</pre>

<h4>Second: The Attribute</h4>
<p>
  The second type is derived from <code>ConfigurationValidatorAttribute</code>
  (which itself derives from <code>System.Attribute</code>). This is used to
  (1) annotate the configuration property in the <code>ConfigurationElement</code> (or
  <code>ConfigurationSection</code>) type, and (2) be an object factory for the first,
  validation, type. Additional parameters can be passed from this attribute to
  the validator.
</p>
<p>
  The key override is <code>ValidatorInstance</code> which needs to return an
  initialised instance of the validator class.
</p>
<p>
  For example, to support the <code>DateTimeValidator</code> type, the following:
</p>
<pre>  [AttributeUsage(AttributeTargets.Property)]
  public class DateTimeValidatorAttribute : ConfigurationValidatorAttribute {
    public DateTimeValidatorAttribute() {
    }

    public override ConfigurationValidatorBase ValidatorInstance {
      get {
        return new DateTimeValidator(new DateTime(minYear, 1, 1));
      }
    }

    private int minYear = 1900;
    public int MinimumYear {
      get { return minYear; }
      set { minYear = value; }
    }
  }
</pre>

<h4>Using Validation</h4>
<p>
  The only change is to annotate the configuration property with the just defined
  attribute, passing any necessary additional parameters, e.g.:
</p>
<pre>  [ConfigurationProperty("startDate", IsRequired=true),
   DateTimeValidator(MinimumYear=2000)]
  public DateTime StartDate {
    get { return (DateTime)this["startDate"]; }
    set { this["startDate"] = value; }
  }

  [ConfigurationProperty("endDate", IsRequired=true),
   DateTimeValidator()]
  public DateTime EndDate {
    get { return (DateTime)this["endDate"]; }
    set { this["endDate"] = value; }
  }
</pre>
<p>
  Note the use of an explicit lower limit for <code>StartDate</code> but not for
  <code>EndDate</code>. (<code>DateTime</code> is not a type with literals
  available for attribute parameters, hence just using the year here.)
</p>

<h3>What Happens on Validation Failure?</h3>
<p>
  Validation is performed when the configuration section is read, i.e. when
  <code>Configuration.GetSection(&lsaquo;<em>name</em>&rsaquo;)</code> is
  called. Importantly this means that if configuration sections are not used,
  validation will not be performed, and no errors will be reported, however many
  invalid, missing or extra values there are. Also note that extra attributes
  and elements will be reported as errors, this behaviour can be modified by
  overriding <code>ConfigurationElement</code>&rsquo;s <code>
  OnDeserializeUnrecognizedAttribute</code> or <code>
  OnDeserializeUnrecognizedElement</code>.
</p>
<p>
  When an error, validation or otherwise (including malformed XML) occurs a
  <code>ConfigurationErrorsException</code> is thrown. If this is based
  on another exception being thrown internally (e.g. on malformed XML, a
  <code>XmlException</code>) then that original exception may be the
  <code>ConfigurationErrorsException</code>&rsquo;s <code>InnerException</code>
  (sometimes this seems to be the base, other times not&mdash;I don&rsquo;t see
  much consistency).
</p>
<p>
  Any reporting of this to the user or logging is up to the application, this is
  not trivial as while the text of the message does include key information
  (like where the error was in the configuration file) it is not exactly in
  a user friendly format. But then configuration files are not targeted at
  (typical) end user direct editing.
</p>


<h3>Checking Values Together</h3>
<p>
  There is no direct support for further validation after
  each individual value has been loaded and (given suitable attributes)
  validated. But <code>ConfigurationElement</code> does have the
  <code>PostDeserialize</code> method, which is called at the right time.
</p>
<p>
  But the error message is not ideal, starting with the text:
  &ldquo;An error occurred creating the configuration section handler for
  &lsaquo;<em>section-name</em>&rsaquo;&rdquo;. But it does work.
</p>
<p>See the code for AppConfigSection.cs for an example</p>

<h3 id='solution'>The Complete Solution</h3>
<h4>DateTimeValidator.cs</h4>
<pre>namespace ConfigurationDemoPart3 {
  public class DateTimeValidator : ConfigurationValidatorBase {
    private DateTime lowerLimit;

    internal DateTimeValidator(DateTime lowerLimit) {
      this.lowerLimit = lowerLimit;
    }

    public override bool CanValidate(Type type) {
      return type.Equals(typeof(DateTime));
    }

    public override void Validate(object value) {
      Trace.Assert(value.GetType().Equals(typeof(DateTime)));
      DateTime val = (DateTime)value;

      // MinValue is used as a placeholder before the actual value is set
      if (val &lt; lowerLimit && val != DateTime.MinValue) {
        throw new ArgumentException("Invalid DateTime value in configuration");
      }
    }
  }

  [AttributeUsage(AttributeTargets.Property)]
  public class DateTimeValidatorAttribute : ConfigurationValidatorAttribute {
    public DateTimeValidatorAttribute() {
    }

    public override ConfigurationValidatorBase ValidatorInstance {
      get {
        return new DateTimeValidator(new DateTime(minYear, 1, 1));
      }
    }

    private int minYear = 1900;
    public int MinimumYear {
      get { return minYear; }
      set { minYear = value; }
    }
  }
}</pre>
<h4>AppConfigSection.cs</h4>
<pre>namespace ConfigurationDemoPart3 {
  public class AppConfigSection : ConfigurationSection {

    [ConfigurationProperty("startDate", IsRequired=true),
     DateTimeValidator(MinimumYear=2000)]
    public DateTime StartDate {
      get { return (DateTime)this["startDate"]; }
      set { this["startDate"] = value; }
    }

    [ConfigurationProperty("endDate", IsRequired=true),
     DateTimeValidator()]
    public DateTime EndDate {
      get { return (DateTime)this["endDate"]; }
      set { this["endDate"] = value; }
    }

    protected override void PostDeserialize() {
      if (StartDate &gt; EndDate) {
        throw new ArgumentException("EndDate must be after StartDate");
      }
      base.PostDeserialize();
    }
  }
}</pre>
<h4>Program.cs</h4>
<pre>namespace ConfigurationDemoPart3 {
  class Program {
    static void Main(string[] args) {
      var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
      ShowSection(config, "custom");
      ShowSection(config, "custom2");
    }

    private static void ShowSection(Configuration config, string secName) {
      try {
        var customSection = config.GetSection(secName) as AppConfigSection;

        Console.WriteLine("Config section \"{2}\": start = {0:d}, end = {1:d}", customSection.StartDate, customSection.EndDate, secName);

      } catch (ConfigurationErrorsException e) {
        var inner = e.InnerException;
        Console.WriteLine("Loading config section \"{0}\" failed: {1} (inner type {2})",
          secName, e.Message, inner == null ? "&lt;None&gt;" : inner.GetType().Name);
      }
    }
  }
}</pre>
<h4>app.config</h4>
<pre>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;configuration&gt;
  &lt;configSections&gt;
  &lt;section name="custom"
       type="ConfigurationDemoPart3.AppConfigSection, ConfigurationDemoPart3"/&gt;
  &lt;section name="custom2"
       type="ConfigurationDemoPart3.AppConfigSection, ConfigurationDemoPart3"/&gt;
  &lt;/configSections&gt;

  &lt;custom startDate="2000-05-20" endDate="2010-05-22"/&gt;
  &lt;custom2 startDate="2010-05-20" endDate="2009-05-22"/&gt;
&lt;/configuration&gt;</pre>

<h3 id='prev-parts'>Previous Part of This Series on .NET Custom Configuration</h3>
<ol>
  <li><a href='/2010/05/17/custom-configuration-1/'>Demonstrating Custom Configuration Sections for .NET</a></li>
  <li><a href='/2010/05/21/custom-configuration-2/'>Demonstrating Custom Configuration for .NET (Part 2): Custom Elements</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.rjcox.co.uk/2010/05/23/custom-configuration-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Demonstrating Custom Configuration for .NET (Part&#160;2): Custom Elements</title>
		<link>http://blog.rjcox.co.uk/2010/05/21/custom-configuration-2/</link>
		<comments>http://blog.rjcox.co.uk/2010/05/21/custom-configuration-2/#comments</comments>
		<pubDate>Fri, 21 May 2010 15:51:44 +0000</pubDate>
		<dc:creator>Richard</dc:creator>
				<category><![CDATA[.NET Core]]></category>

		<guid isPermaLink="false">http://blog.rjcox.co.uk/?p=132</guid>
		<description><![CDATA[Allowing Richer Structures by Adding Custom Elements

Introduction

  Previous Parts of This Series.



  Part 1 kept things really
  simple. But for non-trivial custom configuration just having XML attributes to
  work with starts to get very hard to edit in the file. Rather one wants to
  employ the richer hierarchical structures that [...]]]></description>
			<content:encoded><![CDATA[<h2>Allowing Richer Structures by Adding Custom Elements</h2>

<h3>Introduction</h3>
<p>
  <a href='#prev-parts'>Previous Parts of This Series</a>.
</p>

<p>
  <a href='/2010/05/17/custom-configuration-1/'>Part 1</a> kept things really
  simple. But for non-trivial custom configuration just having XML attributes to
  work with starts to get very hard to edit in the file. Rather one wants to
  employ the richer hierarchical structures that XML allows: child elements.
  This turns out to be very easy.
</p>

<h3>Creating A Custom Element</h3>
<p>
  To keep things simple, this example will just change part 1&rsquo;s structure:
</p>
<pre>&lt;custom date="2010-05-13" name="element name" /&gt;</pre>
<p>into this:</p>
<pre>&lt;custom&gt;
  &lt;data date="2010-05-21" name="custom data name"/&gt;
&lt;/custom&gt;</pre>

<p>
  All this takes is deriving a new class from <code>System.Configuration.ConfigurationElement</code>
  with code attributes for the two configuration attributes, and then using this new
  type as the type of the code property in the <code>ConfigurationSection</code> derived
  class. <a href='#solution'>See the source code below</a>: <code>DataConfigurationElement</code>
  is the new custom element, and <code>AppConfigSection</code> is the updated custom section,
  now with just a single code property.
<p>
<p>
  One limitation of this use of attributes is that text content is not supported
  (<code>&lt;element&gt;text content&lt;/element&gt;</code>), custom elements still
  just use attributes, or child custom elements (there does not seem to be any
  depth limit). <em>Unless</em> one completely overrides the de-serialisation code
  that makes custom elements easy (by overriding the
  <a href='http://msdn.microsoft.com/en-us/library/system.configuration.configurationelement.deserializeelement.aspx'><code>ConfigurationElement.DeserializeElement</code></a>
  method), but then all the work&mdash;including parsing the attributes&mdash;would
  have to be manually coded using the passed <code>XmlReader</code> instance.
</p>

<h3 id='solution'>The Complete Solution</h3>
<h4>DataConfigurationElement.cs</h4>
<pre>namespace ConfigurationDemoPart2 {
  public class DataConfigurationElement : ConfigurationElement {
    [ConfigurationProperty("date", IsRequired=true)]
    public DateTime Date {
      get { return (DateTime) this["date"]; }
      set { this["date"] = value; }
    }
    [ConfigurationProperty("name", IsRequired=true)]
    public string Name {
      get { return (string)this["name"]; }
      set { this["name"] = value; }
    }
  }
}</pre>
<h4>AppConfigSection.cs</h4>
<pre>namespace ConfigurationDemoPart2 {
  public class AppConfigSection : ConfigurationSection {

    [ConfigurationProperty("data", IsRequired=true)]
    public DataConfigurationElement Data {
      get { return (DataConfigurationElement)this["data"]; }
      set { this["data"] = value; }
    }
  }
}</pre>
<h4>Program.cs</h4>
<pre>namespace ConfigurationDemoPart2 {
  class Program {
    static void Main(string[] args) {
      var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
      var customSection = config.GetSection("custom") as AppConfigSection;
      var dataElement = customSection.Data;

      Console.WriteLine("Config: date = {0}, name = {1}", dataElement.Date, dataElement.Name);
    }
  }
}</pre>
<h4>app.config</h4>
<pre>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;configuration&gt;
  &lt;configSections&gt;
    &lt;section name="custom"
             type="ConfigurationDemoPart2.AppConfigSection, ConfigurationDemoPart2"/&gt;
  &lt;/configSections&gt;

  &lt;custom&gt;
    &lt;data date="2010-05-21" name="custom data name"/&gt;
  &lt;/custom&gt;
&lt;/configuration&gt;</pre>

<h3 id='prev-parts'>Previous Part of This Series on .NET Custom Configuration</h3>
<ol>
  <li><a href='/2010/05/17/custom-configuration-1/'>Demonstrating Custom Configuration Sections for .NET</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.rjcox.co.uk/2010/05/21/custom-configuration-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Demonstrating Custom Configuration Sections for .NET (Part 1)</title>
		<link>http://blog.rjcox.co.uk/2010/05/17/custom-configuration-1/</link>
		<comments>http://blog.rjcox.co.uk/2010/05/17/custom-configuration-1/#comments</comments>
		<pubDate>Mon, 17 May 2010 17:47:31 +0000</pubDate>
		<dc:creator>Richard</dc:creator>
				<category><![CDATA[.NET Core]]></category>
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://blog.rjcox.co.uk/?p=128</guid>
		<description><![CDATA[A Simple Starting Point: Single Element with Attributes

Introduction

  The &#60;appSettings&#62; element of a .NET
  .config with the ConfigurationSettings.AppSettings
  static collection to read them make adding a few simple string configuration
  settings to an application easy.
  But, limited to simple name-value pairs, this is (to put it nicely) limited.
  And [...]]]></description>
			<content:encoded><![CDATA[<h2>A Simple Starting Point: Single Element with Attributes</h2>

<h3>Introduction</h3>
<p>
  The <code>&lt;appSettings&gt;</code> element of a .NET
  <code>.config</code> with the <code>ConfigurationSettings.AppSettings</code>
  static collection to read them make adding a few simple string configuration
  settings to an application easy.
  But, limited to simple name-value pairs, this is (to put it nicely) limited.
  And then one compares it to the richness of structure (for example) the CLR
  and ASP.NET support.
  However all that capability to create rich hierarchical structures, including
  multiple types of collections with all values validated is also open to
  the developer.
</p>
<p>
  It is just not obvious where to start (at least the documentation for .NET 4,
  e.g. <a href="http://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.aspx">here</a>,
  is a big improvement over .NET 2's).
</p>
<p>
  Hence this series of posts which aim to be an aide-mémoire of various
  scenarios for different types of <code>.config</code> structures.
</p>


<h3>Keeping It Simple: A Single Element</h3>
<p>
  How to add this
</p>
<pre>
  &lt;custom date="2010-05-13" name="some text" /&gt;
</pre>
<p>
  to the application (or ASP.NET) configuration file?
</p>
<p>
  <strong>Note:</strong> both XML and C# code have attributes, so I&rsquo;ll write
  <em>configuration</em> attribute for XML attributes on the config file, and
  <em>code</em> attribute for those in the source code.
</p>

<h4>Setting Up The Project</h4>
<p>
  Any kind of .NET project can be used, I&rsquo;m using
  C# in a console project here (so I can just focus on configuration).
  This will also work against a .NET 2, 3, 3.5 or 4
  target. The sample here is a console application called
  <code>ConfigurationDemoPart1</code>, so that will also
  be the namespace.
</p>
<p>
  Start by adding a reference to the <code>System.Configuration</code>
  assembly.
</p>
<p>
  Then add a new public class, for this sample called <code>AppConfigSection</code>.
  Derive from <code>System.Configuration.ConfigurationSection</code>. This base
  is needed for any custom type that is referenced by the
  <code>&lt;configSections&gt;</code> to define the configuration file section
  being created.
</p>

<h4>Defining Attributes on the Configuration Element</h4>
<p>
  To create each configuration attribute to appear on the custom element add a
  property to the section class.
</p>
<p>
  Each property needs a <code>System.Configuration.ConfigurationPropertyAttribute</code>
  code attribute with the name of the configuration attribute, and must use
  the default dictionary inherited from <code>ConfigurationSection</code> as a backing store: do
  <em>not</em> use automatic properties or a local field. The key name used in the
  dictionary must match the name in the <code>ConfigurationProperty</code>.
</p>
<p>This is easier to show by example than explain:</p>
<pre>
  [ConfigurationProperty("date")]
  public DateTime Date {
      get { return (DateTime)this["date"]; }
      set { this["date"] = value; }
  }
</pre>

<h4>Accessing the Custom Configuration</h4>
<p>
  Without this the whole effort would be pointless, why write configuration
  file content if you are not going to use it?
</p>
<p>
  Create an instance of <code>System.Configuration.Configuration</code> by using
  the <code>OpenExeConfiguration</code> method of
  <code>System.Configuration.ConfigurationManager</code>. Pass
  <code>System.Configuration.ConfigurationUserLevel.None</code> to just
  access the application configuration file (or <code>web.config</code>).
  Per-user configuration files, and directly loading a specific file (i.e.
  not the default name) is also possible, but that&rsquo;s something for
  later.
</p>
<p>
  Get to the custom configuration with <code>GetSection(<em>name</em>)</code>
  and casting to the custom configuration type. The properties will have the
  values from the configuration file.
</p>
<p>
  You can also set the value of the properties. While this will change the
  value subsequent reads of the properties returns it will not change the
  configuration file. It is possible to save changes, but that&rsquo;s a topic
  for a later post.
</p>

<h4>Adding To The Configuration File</h4>
<p>
  As well as adding the new custom element, the configuration system
  needs to be told about the new element. Do this with the
  <code>&lt;configSections&gt;</code> element, giving the new section
  a name (which you also need to pass, in code, to <code>GetSection</code>)
  and a type:
</p>
<pre>  &lt;configSections&gt;
    &lt;section name="custom"
             type="ConfigurationDemoPart1.AppConfigSection, ConfigurationDemoPart1"/&gt;
  &lt;/configSections&gt;</pre>

<h4>Possible Errors</h4>
<p>
  A null reference on accessing a property in code to get a configuration
  attribute&rsquo;s value probably means one of the code attribute on
  the custom configuration property, the index into the values dictionary
  or the configuration attribute is spelt differently. (This took ages to
  work out the first time it happened to me, now it is always the first
  thing to check.)
</p>


<h3>The Complete Solution</h3>
<h4>AppConfigSection.cs</h4>
<p>This defines the custom type</p>
<pre>  namespace ConfigurationDemoPart1 {
    public class AppConfigSection : ConfigurationSection {

      [ConfigurationProperty("date")]
      public DateTime Date {
        get { return (DateTime)this["date"]; }
        set { this["date"] = value; }
      }

      [ConfigurationProperty("name")]
      public string Name {
        get { return (String)this["name"]; }
        set { this["name"] = value; }
      }
    }
  }</pre>

<h4>Program.cs</h4>
<p>Minimal demonstration code using the custom configuration<p>
<pre>  namespace ConfigurationDemoPart1 {
    class Program {
      static void Main(string[] args) {
        var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
        var customSection = config.GetSection("custom") as AppConfigSection;

        Console.WriteLine("Config: date = {0}, name = {1}", customSection.Date, customSection.Name);
      }
    }
  }</pre>

<h4>app.config</h4>
<p>
  Visual Studio will convert this to <code>ConfigurationDemoPart1.exe.config</code>
  when the project is built.
</p>
<pre>  &lt;configuration&gt;
    &lt;configSections&gt;
      &lt;section name="custom"
               type="ConfigurationDemoPart1.AppConfigSection, ConfigurationDemoPart1"/&gt;
    &lt;/configSections&gt;

    &lt;custom date="2010-05-13" name="element name" /&gt;
  &lt;/configuration&gt;</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.rjcox.co.uk/2010/05/17/custom-configuration-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

