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

  • Compare New GitHub Copilot Free Plan for Visual Studio/VS Code to Paid Plans

    The free plan restricts the number of completions, chat requests and access to AI models, being suitable for occasional users and small projects.

  • Diving Deep into .NET MAUI

    Ever since someone figured out that fiddling bits results in source code, developers have sought one codebase for all types of apps on all platforms, with Microsoft's latest attempt to further that effort being .NET MAUI.

  • Copilot AI Boosts Abound in New VS Code v1.96

    Microsoft improved on its new "Copilot Edit" functionality in the latest release of Visual Studio Code, v1.96, its open-source based code editor that has become the most popular in the world according to many surveys.

  • AdaBoost Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the AdaBoost.R2 algorithm for regression problems (where the goal is to predict a single numeric value). The implementation follows the original source research paper closely, so you can use it as a guide for customization for specific scenarios.

  • Versioning and Documenting ASP.NET Core Services

    Building an API with ASP.NET Core is only half the job. If your API is going to live more than one release cycle, you're going to need to version it. If you have other people building clients for it, you're going to need to document it.

Subscribe on YouTube