by Keyvan Nayyeri via Keyvan Nayyeri on 8/20/2008 6:37:44 PM
Having a powerful and extensible configuration system is a common facet of any application. Almost all the times this configuration system is based on XML files. In .NET world, there is a built-in mechanism for configuration management for application configuration files (App.Config or Web.Config) that lets you add some custom sections as you wish and work with them via a rich set of APIs.
But the problem is that this mechanism is limited and for some applications with more configuration prerequisites it can’t be very proper. So many of the real world professional .NET applications (especially ASP.NET web applications) have their own configuration system based on XML .config files. In such systems you parse XML data and retrieve whatever you want manually.
This is the common method based on XML manipulation API in .NET 1.x, 2.0 and 3.0. Here in a new post series where I want to talk about building such a mechanism with older API and also with XLinq API in two separate posts to show the power of XLinq in .NET Framework 3.5.
The current post is about building this XML configuration system with older XML classes provided in the .NET Framework.
The process of writing such a configuration system consists of a few steps that are all simple and straightforward.
First you need to define properties that are mostly related to configuration data in your file. Then you need to load an XML data into memory and write appropriate methods to parse the data and set the properties.
Beside this, you also need to apply a caching mechanism to improve the performance of your code because usually XML configuration classes are called frequently and it doesn’t sound like a good idea to run all these operations whenever the code is called.
Now let’s take a closer look at this process.
Obviously the first step is to create an XML file that keeps your configuration data. You can give any special structure to this file as you like. Here I create a sample file that will cover all the main concepts that I want to discuss.
<?xml version="1.0"?>
<Keyvan>
<Site
domainName="Site.Com"
siteTitle="Site Title"
siteDescription="A description for your site."
siteKeywords=".net, asp.net, C#, keyvan, nayyeri"
useSsl = "true"
sitePageSize="10"
/>
<Data operationBatchSize="200" />
<Tasks>
<Task name="Emailing"
type="XmlConfigurationSample.Emailing, XmlConfigurationSample"
interval="600000"
enabled="true"
priority="1" />
</Tasks>
</Keyvan>
This file keeps some site related information as well as an element for bulk data operations and a section for scheduled tasks. You can use this section in conjunction with your task scheduling system. As example is our Abidar task scheduler for the ASP.NET that can simply work with such a configuration system. I had written about Abidar with sample code before.
The first step is to create a class. I create this class and name it Config1. Later I will work on Config2 to load my configuration with XLinq.
I need to create some fields and properties for this class. I require two fields. One fields is an XmlDocument that keeps the data for my XML configuration file and will be used throughout this process to work with the configuration file. The other field is a string cache key that will be used to store my configuration data into cache to improve the performance.
I also need to create some read only properties for the information stored in my configuration file. So I need to create some string and integer properties as you see in the below code.
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Xml;
using System.Web.Caching;
namespace XmlConfigurationSample.Code
{
public class Config1
#region Fields
private XmlDocument _xmlDoc = null;
private const string _cacheKey = "KeyvanConfiguration";
#endregion
#region Properties
#region Site
private string _siteDomainName = "site.com";
public string SiteDomainName
get
return this._siteDomainName;
}
private string _siteTitle = "Site Title";
public string SiteTitle
return this._siteTitle;
private string _siteDescription = string.Empty;
public string SiteDescription
return this._siteDescription;
private int _sitePageSize = 10;
public int SitePageSize
return this._sitePageSize;
#region Data
private int _operationBatchSize = 100;
public int OperationBatchSize
return this._operationBatchSize;
My configuration class also needs a public constructor with a custom implementation. In this constructor I get an XmlDocument as parameter to set _xmlDoc field. Note that LoadValuesFromXmlDocument is a private method that I will cover later.
#region Public Constructors
public Config1()
public Config1(XmlDocument doc)
this._xmlDoc = doc;
try
LoadValuesFromXmlDocument();
catch
// TODO: Handle Exception
There are also some public methods that are very important when dealing with the configuration system. The first and most important method is static Load method. This public function returns an instance of the Config1 class. Its internal working consists of loading an instance of the configuration class with all the configuration data and returning it back to the caller. This is the entrance point for users when using the configuration system.
public static Config1 Load()
Config1 configuration = new Config1();
if (HttpRuntime.Cache.Get(_cacheKey) != null)
configuration = HttpRuntime.Cache.Get(_cacheKey) as Config1;
else
string path = HttpContext.Current.Server.MapPath("~/config/keyvan.config");
XmlDocument doc = new XmlDocument();
doc.Load(path);
configuration = new Config1(doc);
HttpRuntime.Cache.Insert(_cacheKey, configuration, new CacheDependency(path),
DateTime.MaxValue, new TimeSpan(12, 0, 0));
return configuration;
But how does it work? First it checks if there is an existing configuration object stored in the cache. If there is any object, then it will return the object and this has a huge impact on the performance. But if it doesn’t exist in the cache, then it loads XML configuration content into an XmlDocument and passes this object to the public constructor to load values. It finally inserts this object into the cache.
Beside this, there are also three other helper methods for the configuration system that can either be used by the configuration class to load values or be called by other classes to get access to a part of the configuration.
There is a GetTasksNodes function that returns an XmlNodeList as well as GetConfigSection and GetConfigSections functions that return an XmlNode and XmlNodeList by getting an XPath query respectively. These latter functions are used by other configuration methods internally.
public XmlNodeList GetTasksNodes()
return GetConfigSections("Keyvan/Tasks/Task");
public XmlNode GetConfigSection(string nodePath)
return this._xmlDoc.SelectSingleNode(nodePath);
public XmlNodeList GetConfigSections(string nodesPath)
return this._xmlDoc.SelectNodes(nodesPath);
But the last step of the development is, implementing a method that loads values from the internal XmlDocument to properties of the configuration class. This is as easy as some regular XML manipulation code.
#region Private Methods
private void LoadValuesFromXmlDocument()
// Site
XmlNode node = GetConfigSection("Keyvan/Site");
XmlAttributeCollection attributes = node.Attributes;
XmlAttribute attribute = attributes["domainName"];
if (attribute != null)
this._siteTitle = attribute.Value;
attribute = attributes["siteTitle"];
attribute = attributes["siteDescription"];
this._siteDescription = attribute.Value;
attribute = attributes["sitePageSize"];
this._sitePageSize = int.Parse(attribute.Value);
// Data
node = GetConfigSection("Keyvan/Data");
attributes = node.Attributes;
attribute = attributes["operationBatchSize"];
this._operationBatchSize = int.Parse(attribute.Value);
After all, my configuration class is something like this:
#region Public Methods
XmlAttribute attribute = attributes["siteDomainName"];
At this point, I’m able to test my configuration system. I can write a code that loads site title and description from this configuration system to set them for a page.
protected void Page_Load(object sender, EventArgs e)
Config1 config = Config1.Load();
this.Page.Title = config.SiteTitle;
HtmlMeta description = new HtmlMeta();
description.Attributes.Add("name", "description");
description.Attributes.Add("content", config.SiteDescription);
this.Page.Header.Controls.Add(description);
Note that I have created a new instance of Config1 class by calling the Load function.
In the next part I will rewrite this configuration system with XLinq. Let me publish the source code sample for this part along the second part.
Original Post: Building a Custom XML Configuration System for ASP.NET – Part 1
The content of the postings is owned by the respective author. CSharpFeeds is not responsible for the contents of the postings. This site is automatically generated and cannot be reviewed for abusive content. If you find abusive content on CSharpFeeds, please contact us. Designated trademarks and brands are the property of their respective owners. All rights reserved.