The AppConfiguration class can be configured with custom configuration providers that allow storage of configuration information in different, non-config file based storage mechanisms. This mechanism allows for various additional formats that are provided as well as for you to extend with custom providers. The additional providers available are:

All three of these formats use XmlSerialization to serialize the configuration settings.

The following examples assume the following configuration class setup:

public class ApplicationConfiguration : Westwind.Utilities.Configuration.AppConfiguration { public ApplicationConfiguration() { } public ApplicationConfiguration( IConfigurationProvider provider) { if (provider == null) { provider = new ConfigurationFileConfigurationProvider<ApplicationConfiguration>() { PropertiesToEncrypt = "ConnectionString,MailServerPassword" }; } this.Provider = provider; this.Read(); } public string ConnectionString { get { return _ConnectionString; } set { _ConnectionString = value; } } private string _ConnectionString = "WestwindAdmin"; public int ItemsPerListPage { get { return _ItemsPerListPage; } set { _ItemsPerListPage = value; } } private int _ItemsPerListPage = 10; public string MailServerPassword { get { return _MailServerPassword; } set { _MailServerPassword = value; } } private string _MailServerPassword = "secret"; }

Please note that the class above is defaulted to use the ConfigurationFileConfigurationProvider, but you can override the default behavior substituting one of the other providers discussed below or a custom provider you build.

XmlFileConfigurationProvider

The Xml file provider allows writing to file that is not in .NET configuration format and can have basically any structure. It uses XML Serialization so it's possible with this scheme to include nested sub-objects in the configuration class, which is not possible with standard config files that use plain key value pairs.

Stick with ConfigurationFileConfigurationProvider unless you need nested types
In general, unless you require a special configuration format that requires nested types we recommend you stick with standard .NET configuration files using the ConfigurationFileConfigurationProvider because it provides additional features such as configuration file change detection in Web apps.

Here's a test that demonstrates using the the XmlFileConfigurationProvider:

[TestMethod] public void XmlFileConfiguration_Encrypted_Test() { string expectedPassword = "New Password"; int expectedItemsPerPage = 15; // Load without any specific provider since we're going to // plain string values ApplicationConfiguration config = new ApplicationConfiguration(new XmlFileConfigurationProvider<ApplicationConfiguration>() { PropertiesToEncrypt = "ConnectionString,MailServerPassword", XmlConfigurationFile = "ApplicationConfiguration.xml", // Server.MapPath("~/ApplicationConfiguration.xml"); UseBinarySerialization = false }); // set new values config.MailServerPassword = expectedPassword; config.ItemsPerListPage = expectedItemsPerPage; // write output to the file with new values (permissions required) config.Write(); Console.WriteLine(Environment.CurrentDirectory); // clear out values to make sure config.MailServerPassword = ""; config.ItemsPerListPage = 0; // Re-read configuration from the file config.Read(); Assert.AreEqual<string>(expectedPassword, config.MailServerPassword, "Updated encrypted value doesn't match"); Assert.AreEqual<int>(expectedItemsPerPage, config.ItemsPerListPage, "Updated encrypted value doesn't match"); }

SqlServerConfigurationProvider

Like the Xml file provider the Sql Server provider uses XML Serialization that works through string serialization that is then stored in the database in a single field. The idea is that you have a single table with a specific structure that can hold one or more configuration records in an nText field of the database.

The table will be auto-created for you if it doesn't exist - assuming you have rights to do so. The default structure looks like this:

CREATE TABLE [{0}] ( [id] [int] , [ConfigData] [ntext] COLLATE SQL_Latin1_General_CP1_CI_AS)

The provider includes options for configuring the ConnectionString to the database, the Tablename and the Key value (integer) which determines which record is written. You can have many different configuration settings based on the integer ids.

Note that the connection string can either be a full SQL Server or SQL Compact connection string or the name of a <ConnectionStrings> key from the app's .config file.

Here's an example test setup using the Sql Server configuration provider:

[TestMethod] public void SqlConfiguration_Encrypted_Test() { string expectedPassword = "New Password"; int expectedItemsPerPage = 15; ApplicationConfiguration config = new ApplicationConfiguration(new SqlServerConfigurationProvider<ApplicationConfiguration>() { ConnectionString = "WestwindAdmin", TableName = "ApplicationConfigurationSettings", // Key = 1, PropertiesToEncrypt = "ConnectionString,MailServerPassword" } ); config.MailServerPassword = expectedPassword; config.ItemsPerListPage = expectedItemsPerPage; config.Write(); config.MailServerPassword = ""; config.ItemsPerListPage = 0; // re-read from store config.Read(); Assert.AreEqual<string>(expectedPassword, config.MailServerPassword,"Updated encrypted value doesn't match"); Assert.AreEqual<int>( expectedItemsPerPage, config.ItemsPerListPage, "Updated encrypted value doesn't match"); }

Reading and Writing String Configuration Settings

You can also read and write string configuration settings using any of the providers or the limited StringConfigurationProvider. String retrieval and writing work only with the Read() method that supplies a string parameter, WriteAsString() and the static Read method.

The following test demonstrates how to read and write values using strings:

[TestMethod] public void StringConfiguration_Encrypted_Test() { string expectedPassword = "New Password"; int expectedItemsPerPage = 15; // Load without any specific provider since we're going to // plain string values - no provider is required ApplicationConfiguration config = new ApplicationConfiguration( new StringConfigurationProvider() { PropertiesToEncrypt = "MailServerPassword,ConnectionString"; }); // set new values config.MailServerPassword = expectedPassword; config.ItemsPerListPage = expectedItemsPerPage; // write output to string string result = config.WriteAsString(); TestContext.WriteLine(result); // clear out values to make sure config.MailServerPassword = ""; config.ItemsPerListPage = 0; // Re-read configuration from our saved string config.Read(result); Assert.AreEqual<string>(expectedPassword, config.MailServerPassword, "Updated encrypted value doesn't match"); Assert.AreEqual<int>(expectedItemsPerPage, config.ItemsPerListPage, "Updated encrypted value doesn't match"); }

String retrieval is useful for applications that need to store output into non-supported storage mechanisms. By retrieving strings you can effectively write into any store that supports string based storage with a simple wrapper routine. This string support can also serve as a base implementations for custom providers you might implement yourself with the WriteAsString() and Read() overloads for string inputs available on the base ConfigurationProviderBase implementation.