.Net Client

We expect that most consumers that are using a .Net server will want to use our client library. MySpace has a section handler called "XmlSerializerSectionHandler" for reading and reloading XML configuration files on the local filesystem (which is included in the released source code under the Shared library), so we created the creatively named "XmlSerializerReplacementHandler". Included in the code is a project called "XmlSerializerExample" which demonstrates how to use this with a console application.

For other handlers or specialized uses, you may wish to tie into the client directly, so both methods are described below.

Overall Client Config

Though we tried to keep it minimal for obvious reasons, the client does require SOME configuration of its own. There is one exception: if you have a configuration server with the DNS name "configserver", you can completely omit client configuration and it will use sensible defaults and that server name.

The section definition looks like

<section name="ConfigurationSystemClientConfig" type="MySpace.ConfigurationSystem.ConfigurationSystemClientConfig, MySpace.ConfigurationSystem.Client"/>

and the configuration block should look something like

<ConfigurationSystemClientConfig remoteHost="configserver:80" />

Additional Options

The above config should be sufficient for most cases, but there are a few other options. Below are all of the attributes for the <ConfigurationSystemClientConfig> element.
  • remoteHost
    • The address the client will use for configuration requests.
    • Default is "localhost:9000"
  • sectionCheckIntervalSeconds
    • The client polls the server for updates to all configs it has served locally, and this attribute determines the polling interval.
    • Default is "60"
  • failoverStrategy
    • Either "ThrowException" or "UseLocal"
    • This controls what the client will do if there is an problem when updating a locally cached config.
      • If "UseLocal", then the client will simply use the local copy.
      • If "ThrowException", then the client will throw an exception with information about the problem.
      • In either case, information about the problem will be logged.
    • Default is "UseLocal"
  • checkOnGet
    • The client polls the server every sectionCheckIntervalSeconds in order to signal clients that a change has occurred, but you can also tell it to poll the server on each request for the config if the local cache is more than that many seconds old.
    • As that check would be performed on the thread that requested the config, this could cause slow operation if there are any problems upstream.
    • Default is "false"
  • keyProviderTypeName
    • The server has the ability to encrypt sections that are served. Because it's not a great idea to store encryption keys in configuration files, they must be provided in code. Please see Section Encryption for more information.

XmlSerializerReplacementHandler

Please see XmlSerializerReplacementHandler for an excruciatingly detailed description of our primary section handler, XmlSerializerReplacementHandler. This is likely what you want to use, as it provides for reading sections remotely, notifying consumers of sections that they have updated, and using local files to override.

ConfigurationClient

The XmlSeriaXmlSerializerReplacementHandler described above uses MySpace.ConfigurationSystem.ConfigurationClient to do its work, and if you want to create your own section handler or hook directly into the client for any other reason, that is the easiest place to start. Of course, you can also hit the server http API directly, but if you are a .Net consumer, the client library does an awful lot for you. And if it doesn't do something you need, like everything else here it is a live product and can be improved so it does!

As the configuration client's only job is getting configuration sections, the API is simple and concise. You can request a section either as a string or as an XmlNode, register to be notified when the section is updated, and inform the client that a section is invalid and should not be cached.

Getting a Section

A section can be supplied either as a raw string, or processed into an XmlNode with the following methods.

string GetSectionString(string sectionName)
XmlNode GetSectionXml(string sectionName)

If there is a problem fetching the config and no local copy is available (or the client is configured to throw exception on every error as described above), then a ConfigurationSystemException will be thrown. A ConfigurationSystemException has two fields, SectionName, and ErrorMessage. Regardless of if any exceptions are thrown, information about the error will be written to log4net.

Change Notification

If you have a method that can handle your configuration section changing, then you can have the configuration client call it when the section has changed. There are two ways to do this - using a standard .net event, or calling a method that will only call your event handler when your section has changed. With either technique, as with all event registrations, you should unregister the event when you are done with your object, otherwise it will never be fully garbage collected.

The event is defined thusly:

public delegate void ConfigurationChangedEventHandler(object sender, ConfigurationChangedEventArgs args);
public static event ConfigurationChangedEventHandler ConfigurationChangedEvent;

ConfigurationChangedEventArgs has a single field: SectionName, which is the name of the section that has changed. This is an example of what getting a configuration node and using the event handler directly might look like:

public void Init()
{
    XmlNode configNode = ConfigurationClient.GetSectionXml("mySectionName");
    //do what you need to do with a config Node
    ConfigurationClient.ConfigurationChangedEvent += ConfigurationChanged;
}

public static void ConfigurationChanged(object s, ConfigurationChangedEventArgs a)
{
    if(a.SectionName == "mySectionName")
    {
        XmlNode sectionNode = ConfigurationClient.GetSectionXml("mySectionName");
        //do stuff with sectionNode
    }
}

public void Shutdown()
{
    ConfigurationClient.ConfigurationChangedEvent -= ConfigurationChanged;
}

The alternate technique is to call the RegisterReloadNotification function:

public void Init()
{
    XmlNode configNode = ConfigurationClient.GetSectionXml("mySectionName");
    //do what you need to do with a config Node
    ConfigurationClient.RegisterReloadNotification("mySectionName", ConfigurationChanged);
}

public static void ConfigurationChanged(object s, ConfigurationChangedEventArgs a)
{
    //this will only be called for the section name you registered with, 
    //so it is not necessary to check the section name 
    XmlNode sectionNode = ConfigurationClient.GetSectionXml("mySectionName");
    //do stuff with sectionNode
}

public void Shutdown()
{
    ConfigurationClient.UnregisterReloadNotification("mySectionName", ConfigurationChanged);
}

Invalid Configs

It is inevitable that sometimes a bad configuration section will be published, so there is a way to notify the configuration client of this so it will remove that config from its cache. If you detect a bad section while loading it, simply call InvalidateSection, as illustrated below.

public void Init()
{		
    XmlNode configNode = ConfigurationClient.GetSectionXml("mySectionName");
    ConfigurationClient.RegisterReloadNotification("mySectionName", ConfigurationChanged);
    try
    {
        //do what you need to do with a config Node
    }
    catch (Exception)
    {
        ConfigurationClient.InvalidateSection("mySectionName");
	throw;
    }
}

Last edited May 23, 2011 at 10:06 PM by eriknelson, version 2

Comments

No comments yet.