Practical .NET

ASP.NET: Extending the Config File with Custom Sections

If you want to do a better job of managing your configuration settings than just throwing random data into appSettings, you can extend your config file with your own custom XML and actually edit your settings.

If you need to store multiple, interdependent values in your config file, the appSettings element gives you no support: It's a miscellaneous collection of untyped values with no relations between them. A better solution is to add custom elements to your config file. It's not a tool I use often, but I was reminded of it when writing a recent article on Windows Identity Foundation, which uses custom sections extensively.

As I suggested, extending the config file is a niche solution -- my first choice for storing user or site configuration settings is in a database table. However, if you need to set the configuration options for an application before a user accesses the database, custom sections in the application's config file are an excellent place to put the information. Using custom sections rather than appSettings also allows you to incorporate any editing you want to ensure that only valid settings are made (or, at least, that your site won't start if there are invalid settings).

One of my clients, for instance, has a Web-based product installed at several of their customers' sites. Options in the web.config file let customers configure how much JavaScript is used in the browser to access data. Here's a very simplified version of the custom configuration section I added to the site's web.config file:

<PHVCustomerOptions>
  <ajaxSettings siteNo="123" ajax="false"/>
</PHVCustomerOptions>

Before going further, let me set your expectations about this technology: It is possible to use an element-based design rather than the attribute-based design you see here. But it would require more code than the technique I'm about to demonstrate -- I don't think it was worth the trouble. You won't get any IntelliSense support or compile-time checking for your custom elements, either.

Build a Custom Element
Your first step is to add a Class Library project to your solution to hold the class that defines your custom elements (defining the class in a separate project allows you to re-use it). Add a reference to the System.Configuration library to the project.

The next step is to add a class for each custom element that inherits from ConfigurationSection. You can give your class any name you want (it won't affect the XML in your config file). To save yourself some typing, put two namespace directives at the top of your class file so that it looks like this:

Imports System.Configuration
Imports System.Configuration.ConfigurationManager

Public Class ajaxConfig
    Inherits ConfigurationSection

Now, for every attribute you want on your element, define a property (your properties can have any name you want). Each property must be decorated with the ConfigurationProperty attribute, which can be passed up to three values. The first value is mandatory and is the name of the attribute as it appears in your config file. The other two named values (DefaultValue and IsRequired) are optional. You can create a read/write property if you intend to allow the config file to be updated from code, but I just created read-only properties. In the getter for the property, use the class' Item method, passing the name of the attribute, to retrieve the attribute's value.

This example defines the ajax attribute from my previous example:

<ConfigurationProperty("ajax", DefaultValue:="False",
 IsRequired:=True)> _
Public ReadOnly Property Ajax() As Boolean
   Get
      Return Convert.ToBoolean(Me.Item("ajax"))
   End Get
End Property 

In these properties you can also check the values for validity and throw an exception, if necessary. And, if you're tired of typing you can omit the ".Item" and even the "Me" to use this code (this looks like "job security" programming to me, though):

      Return Convert.ToBoolean(("ajax"))

To save some coding in your application, add a Shared method to your class that retrieves your element from the config file using the ConfigurationManager's GetSection method and converts the result to your class type:

Public Shared Function GetConfig() As ajaxConfig
  Return CType(GetSection("PHVCustomerOptions/ajaxSettings"), _
    ajaxConfig)
End Function

Integrating the Custom Element
Back in your Web project, after adding a reference to your Class Library project, you're ready to incorporate your custom element. In the configSections element, I use a sectionGroup element to define an enclosing element for all of my custom elements, but it's not required.

With or without the sectionGroup element, you use the section element to integrate your custom elements. The type attribute for the section element must specify the namespace and name of your class file while the name attribute specifies the name your custom element will actually have in your config file. This example nests my CustomConfigurations.ajaxConfig class inside a section called PHVCustomerOptions. My custom element will be called ajaxSettings:

<configSections>
  <sectionGroup name="PHVCustomerOptions">
	<section name="ajaxSettings" 
		   type="CustomConfigurations.ajaxConfig"/>
</sectionGroup>

I can now add this element to my config file:

<PHVCustomerOptions>
    <ajaxSettings ajax="false"/>      
</PHVCustomerOptions>

In my server-side code, I can retrieve the values set in the config file with code like this:

Dim ajaxSetting As CustomConfigurations.ajaxConfig
Dim IsAjax As Boolean

ajaxSetting = CustomConfigurations.ajaxConfig.GetConfig
IsAjax = ajaxSetting.Ajax

You can now either add more attributes to your CustomSection class or create new CustomSections to put inside your SectionGroup. Either way, you'll have a lot more control over your configuration settings than appSettings will ever give you.

About the Author

Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.

comments powered by Disqus

Featured

  • Full Stack Hands-On Development with .NET

    In the fast-paced realm of modern software development, proficiency across a full stack of technologies is not just beneficial, it's essential. Microsoft has an entire stack of open source development components in its .NET platform (formerly known as .NET Core) that can be used to build an end-to-end set of applications.

  • .NET-Centric Uno Platform Debuts 'Single Project' for 9 Targets

    "We've reduced the complexity of project files and eliminated the need for explicit NuGet package references, separate project libraries, or 'shared' projects."

  • Creating Reactive Applications in .NET

    In modern applications, data is being retrieved in asynchronous, real-time streams, as traditional pull requests where the clients asks for data from the server are becoming a thing of the past.

  • AI for GitHub Collaboration? Maybe Not So Much

    No doubt GitHub Copilot has been a boon for developers, but AI might not be the best tool for collaboration, according to developers weighing in on a recent social media post from the GitHub team.

  • Visual Studio 2022 Getting VS Code 'Command Palette' Equivalent

    As any Visual Studio Code user knows, the editor's command palette is a powerful tool for getting things done quickly, without having to navigate through menus and dialogs. Now, we learn how an equivalent is coming for Microsoft's flagship Visual Studio IDE, invoked by the same familiar Ctrl+Shift+P keyboard shortcut.

Subscribe on YouTube