Configuration Sections
Hi,I've just started playing with VS2005. We currently have a VB.NET application which uses a custom config section implemented by declaring a class which implements theIConfigurationSectionHandler interface and which was invoked by declaring it in the <configSections> section of app.config.The section handler so defined parsed a 'systems' configuration section in app.config and returned a collection of objects from its Create method.
The result of this was a <systems> configuration section in app.config which in turn was made up of one or more <system> entries, as for example:
<systems>
<system name="Production", server="someserver", database="proddb" />
<system name="Test", server="testserver", database="testdb" />
<system name="Development", server="devserver", database="devdb" />
etc...
</systems>
These entries allowed the user running the app to select which system they wanted to connect to - the login screen displayed a combo containing elements from the entries from above.
This worked great in VS2003.
When I attempt to convert the app to VS2005, I get compile errors telling me in effect this whole mechanism is obsolete.
Needless to say, the state of the current documentation on the replacement for configuration sections seems a bit sparse, and I cannot figure out what I need to do.
I see that substantial changes were made in this area, allowing for what appears to be a very complete and complex capability for read/write sections, roaming profiles, multiple configuration files, and the like. That's all well and good, but what I'm looking for is a simple replacement for this simple readonly app.config configuration section.
Can anyone point me in the right direction or to some docs which might explain this a little better?
Thanks
Do you run into this problem only when upgrading your project to VS2005 or when you configure your application to run on v2.0 NetFX while still compiled against v1.1 (for info on config see msdn).
Along with our final release we will have more complete documentation about best practices going forward, but existing solutions should still work.
If you find that your app does indeed fail when configured to run on 2.0 this may be a compatibility issue. Please file a bug on MSDN Feedback and mark it as Issue Type: Compatibility.
Thank you,
The CLR Team
A compile error occurs in VS2005 when I try to upgrade my app from VS2003. Specifically, the Configurations class in the System.Configuration namespace seems to have disappeared.
The offending line of code in my app reads:
systemlist = DirectCast(System.Configuration.ConfigurationSettings.GetConfig("systems"), ConfigSystemList)and this generates the error at compile time:
Error 11 'Configurations' is not a member of 'Configuration'. C:\DotNet2005\Phoenix\PhoenixUI\Login.vb 321 34 PhoenixUI
I have defined a class which implements the IConfigurationSectionHandler interface and is referenced in the <configSections> section in the app.config file. This class's Create method parses a <systems> section in app.config and returns a collection of entries in that section (ConfigSystemList as above).
I'm trying to figure out how to do the equivalent thing in 2.0 ...
- Jeff
The v2.0 configuration system should be backwards compatible with v1.x section handlers. The error displayed doesn't seem to match the offending line of code:
'Configurations' is not a member of Configuration
Where are you using the type Configurations? It's not a type that I'm aware of so I am wondering if there is a typo? If possible, would you be able to provide your code so that we could look into it further? thx...
Yeah. My apologies. I posted the error message mid-edit of the offending source code. I had gotten the warning:
Warning 11 'Public Shared Function GetConfig(sectionName As String) As Object' is obsolete: 'This method is obsolete, it has been replaced by ConfigurationManager.GetSection'
on a line of code which read:
systemlist = DirectCast(System.Configuration.ConfigurationSettings.GetConfig("systems"), ConfigSystemList)and I was trying various things in the ConfigurationManager namespace to address the warning when I realized I was totally lost in a maze of new sparsely documented objects and methods. I stopped making changes and made my original posting here. I stupidly forgot to restore things to the way they originally were.I am aware that the message is just a warning, but I am trying to convert my code so it compiles without warnings. I don't like code that compiles with warnings, so I'd like everything 'clean'. This is the last bit of code with "issues"..
I'd be happy to post the code if you think it helpful, but there are several pieces involved. I'll describe the pieces, and if you want more I'd be happy to post all of them.
The ConfigSystemList
type above is a typed collection of ConfigSystemListEntry objects. Those objects simply expose a number of properties which identify the System, Server, Database, and other system related settings. The collection is populated by a SystemsConfigSectionHandler object (located in a 'CACommon' assembly) which implements the System.Configuration.IConfigurationSectionHandler interface.The SystemsConfigSectionHandler is "wired up" via the app.config entry:
<configSections>
<section name="systems" type="CACommon.SystemsConfigSectionHandler, CACommon" />
</
configSections>This object parses app.config entries of the form:
<
systems>
<system name="Production" server="PRODSERVER" database="Prod" default="no"/>
<system name="Demo" server="DEMOSERVER" database="Demo" />
<system name="Testing" server="TESTSERVER" database="Test" default="no"/>
<system name="Development" server="DEVSERVER" database="DEV" default="yes" />
</systems>
It creates one ConfigSystemListEntry object per <system> line and inserts each of them into the ConfigSystemList collection. This collection is then ultimately bound to a combobox to allow the user to pick the system they want to connect to. Among other things, a connection string is built from the selected entry.All I'd like to do is to find the "new" way to implement this capability.
Thanks for your help.
To get your code to compile without the warnings, you'll need to replace your call to
System.Configuration.ConfigurationSettings.GetConfig("systems")
with
System.Configuration.ConfigurationManager.GetSection("systems")This new type lives in the System.Configuration.dll assembly so you'll also need to add a reference to this assembly to your project.To migrate your v1.1 configuration section handler to v2.0, you'll need to re-write your sectionHandler using the new Configuration system base classes which live in the System.Configuration namespace in the System.Configuration.dll assembly. You'll need to use the following classes: ConfigurationSection, ConfigurationElement and ConfigurationElementCollection.
Here's a pretty good link that blogs how to create your own sectionHandler:
http://fredrik.nsquared2.com/viewpost.aspx?PostID=253&showfeedback=true
Implementing the section is really easy:
using System;
using System.Configuration;
using System.ComponentModel;
using System.Globalization;
namespace MyCompany.Configuration
{
public sealed class SystemsSection : ConfigurationSection
{
[ConfigurationProperty("",IsDefaultCollectionProperty=true)]
public SystemsCollection Systems
{
get
{
return (SystemsCollection)base[""];
}
}
}
public sealed class SystemsCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new SystemElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((SystemElement)element).Name;
}
protected override ConfigurationElementCollectionType CollectionType
{
get
{
return ConfigurationElementCollectionType.BasicMap;
}
}
protected override string ElementName
{
get
{
return "system";
}
}
}
public sealed class SystemElement : ConfigurationElement
{
[ConfigurationProperty("name",IsCollectionKey=true,RequiredValue=true)]
public string Name
{
get
{
return (string)base["name"];
}
set
{
base["name"] = value;
}
}
[ConfigurationProperty("server",RequiredValue=true)]
public string Server
{
get
{
return (string)base["server"];
}
set
{
base["server"] = value;
}
}
[ConfigurationProperty("database",RequiredValue=true)]
public string Database
{
get
{
return (string)base["database"];
}
set
{
base["database"] = value;
}
}
[ConfigurationProperty("default")]
[TypeConverter(typeof(YesNoToBooleanConverter))]
public bool Default
{
get
{
return (bool)base["default"];
}
set
{
base["default"] = value;
}
}
}
public class YesNoToBooleanConverter : ConfigurationConverterBase
{
public override object ConvertTo(ITypeDescriptorContext ctx, CultureInfo ci, object value, Type type)
{
bool bValue = (bool)value;
if ( bValue )
return "yes";
return "no";
}
public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data)
{
bool result = false;
string value = (string)data;
if (string.IsNullOrEmpty(value))
throw new ConfigurationErrorsException();
if ( value == "yes")
result = true;
else if ( value == "no" )
result = false;
else
throw new ConfigurationErrorsException();
return result;
}
}
}
I hava a question.I'm using vs2005 TeamSuite.I have created CustomSections, Handlers,etc....It is working fine for a single section element.If I add more than one section it is throwing up an error saying "Sections must only appear once per config file".
Have anyone got this issue already?Can you please explian how to resolve this problem...
Please look through your config file and verify that each xml element that represents a config section only exists once per level. This should include sections within a <location /> path.
If you're still having trouble, please post your config file so we can help to identify the offending section. Thx...
Hi,
How i can read the following app.config file.
<?
xml version="1.0" encoding="utf-8" ?> <
configuration> <
configSections> <
section name="Site" type="ConsoleApplication4.SiteSection, ConsoleApplication4" /> </
configSections> <
Site Run="True"> <
Line Name="Line1" Run="True"> <
Station Name="Station1" Run="True"></Station> <
Station Name="Station2" Run="True"></Station> </
Line> <
Line Name="Line2" Run="True"> <
Station Name="Station3" Run="True"></Station> <
Station Name="Station4" Run="True"></Station> </
Line> </
Site> </
configuration>
Thanks
Satya