Hi folks,
I've recently been confronted with the necessity of using the new .NET 2.0 ConfigurationManager and it's associated classes: ConfigurationElement, ConfigurationSection and ConfigurationElementCollection. What an absolutely horrid exercise in frustration! The documentation is truly awful; none of it mentions what methods need to be overridden/implemented in order to customize any of the above, and I can find no documentation at all in the MSDN Library concerning the ConfigurationAttributes used in working with these classes declaratively. Add to this that every single example I've found online all show manipulation of element properties, but nothing about an element's content! Doesn't anyone put content between XML tags anymore? Any time I try to do so, I get exceptions thrown! How is one to access content between the element tags, particularly CDATA sections?
Specifically, I need to store some regular expressions here, and I'm at my wit's end.
Please forgive me for saying so, Microsoft, but these classes are truly abysmal, and I'm truly annoyed that you foisted them off on us without adequate documentation. You're going to have to go some to convince me that these classes are worth the effort and frustrationencountered in attempting to use them.
Thanks in advance,
Duane T. Doutel
| | Duane Doutel Friday, May 26, 2006 3:01 AM | Hello Duane,
Thank you for the information. With the code, I also found the same exption. After some researching, I didn't found anyone talking about the ConfigurationSection can hanldeCData. So, I think the only way is to override the ConfigurationElement's DeserializeElement and catch the exception. For example:
protected override void DeserializeElement(System.Xml.XmlReader reader, bool serializeCollectionKey) { try { base.DeserializeElement(reader, serializeCollectionKey); } catch (System.Configuration.ConfigurationErrorsException Cee) { StrCData=reader.Value ; }
}
Hope this help,
| | Luke Zhang - MSFT Monday, May 29, 2006 9:21 AM | Hello Duane,
Would you please post somecode here, to demo how you use the classes like:ConfigurationElement, ConfigurationSection and ConfigurationElementCollection? Also what is the exceptions you got? I am take a look at it to see if there any problems. ( Please also post the config file).
Thanks, | | Luke Zhang - MSFT Friday, May 26, 2006 9:00 AM | Hi Luke,
Thanks for replying. Here's a piece of the App.config I've been using. Note that it's been stripped down considerably to show only the salient points, as some of the file's contents are proprietary to the client for whom I'm doing this project:
<configuration>
<configSections>
<section name="CustodianInfo" type="RebateSections.CustodianInfoSection, RBRates" />
</configSections>
<CustodianInfo>
<Custodian
name="UBSS"
protocol="FTP"
sourcePath="%2e%2e/out"
sourceFileName="SL011C.CSV"
destPath="data\UBSS"
destFileName="UBSS"
format="CSV" >
<![CDATA[
(?:^"\w*\s*",")(?<AccountNum>\w*)(?:".")(?<BusinessDateDT>\d*)(?:".")(?<CUSIP>\w*)(?:".")(?<Security>\w*)(?:"."\w*",")(?<SEDOL>\w*)(?:".")(?<Description>[^"]*)(?:".")(?<Shares>[\+|\-|0-9|,|.]*)(?:","\w*",")(?<RebateRate>[\+|\-|0-9|,|.]*)(?:","[\+|\-|0-9|A-Z|,|.]*){4}(?:".")(?<BorrowPrice>[\+|\-|0-9|,|.]*)(?:".")(?<RebateAmount>[\+|\-|0-9|,|.]*)(?:".")(?<IsHotYN>[Y|N])
]]>
</Custodian>
<CustodianInfo>
</configuration>
And here's the code for the section handler:
public class Custodian : ConfigurationElement
{
public Custodian()
{
}
[ConfigurationProperty( "name", IsKey = true, IsRequired = true )]
public string Name
{
get { return (string)this["name"]; }
}
[ConfigurationProperty("protocol", IsRequired = true)]
public string Protocol
{
get{ return (string)this["protocol"];}
}
[ConfigurationProperty("sourcePath", IsRequired = true)]
public string SourcePath
{
get{ return (string)this["sourcePath"]; }
}
[ConfigurationProperty("sourceFileName", IsRequired = true)]
public string SourceFileName
{
get{ return (string)this["sourceFileName"]; }
}
[ConfigurationProperty("destPath", IsRequired = true)]
public string DestPath
{
get{ return (string)this["destPath"]; }
}
[ConfigurationProperty("destFileName", IsRequired = true)]
public string DestFileName
{
get{ return (string)this["destFileName"]; }
}
[ConfigurationProperty ( "format", IsRequired = true )]
public string Format
{
get { return ( string )this[ "format" ]; }
}
[ConfigurationProperty( "PGP", IsRequired = false )]
public string PGP
{
get { return ( string )this[ "PGP" ]; }
}
}
public class CustodianCollection : ConfigurationElementCollection
{
public CustodianCollection ( ) { }
protected override ConfigurationElement CreateNewElement()
{
return new Custodian ( );
}
protected override object GetElementKey(ConfigurationElement element)
{
return ( ( Custodian )element ).Name;
}
public override ConfigurationElementCollectionType CollectionType
{
get { return ConfigurationElementCollectionType.BasicMap; }
}
protected override string ElementName
{
get{ return "Custodian"; }
}
}
public class CustodianInfoSection : ConfigurationSection
{
public CustodianInfoSection ( ) { }
[ConfigurationProperty ( "", IsDefaultCollection = true )]
public CustodianCollection Custodians
{
get { return ( CustodianCollection )base[ "" ]; }
}
}
Here's the exception I get:
Exception The configuration section cannot contain a CDATA or text element. (C:\Dev\Projects\Blue Ridge\Rebates\Work\RBRates\bin\Release\RBRates.exe.config line 30) at System.Configuration.System.Object EvaluateOne(System.String[], System.Configuration.SectionInput, Boolean, System.Configuration.FactoryRecord, System.Configuration.SectionRecord, System.Object)
I've tried setting the DefaultCollection flag on the section's configuration property to false, but get a variety of other exceptions, too numerous to show here.
Is there anywhere in the MSDN library a comprehensive guide to the attributed model used for the ConfigurationManager classes, and a comprehensive guide withnon-trivial examples(ala UrlConfigSection)? XML files I understand and have worked with; without the mentioned comprehensive guide, I see absolutely no advantage to these ConfigurationManager classes!
Thanks in advance,
Duane T. Doutel
| | Duane Doutel Sunday, May 28, 2006 9:21 PM | Hello Duane,
Thank you for the information. With the code, I also found the same exption. After some researching, I didn't found anyone talking about the ConfigurationSection can hanldeCData. So, I think the only way is to override the ConfigurationElement's DeserializeElement and catch the exception. For example:
protected override void DeserializeElement(System.Xml.XmlReader reader, bool serializeCollectionKey) { try { base.DeserializeElement(reader, serializeCollectionKey); } catch (System.Configuration.ConfigurationErrorsException Cee) { StrCData=reader.Value ; }
}
Hope this help,
| | Luke Zhang - MSFT Monday, May 29, 2006 9:21 AM | Hi Luke,
Thanks very much; I'll give this a try right away. Very much appreciated! 
How would I go about getting access to the innerXML of a tag, if needed? I left out a good bit of the file; the regular expressions are not the only large chunks of information I need to retrieve.
Can you give a bit more explanation regarding the use of the ConfigurationElementCollection, and its' IsDefaultCollection attribute? It's not clear how to nest sections within sections. Does one need to have ConfigurationSection-, ConfigurationElement- and ConfigurationElementCollection-derived classes for each such section one might wish to nest? SectionGroups are also not really dealt with in any of the documentation. How about some more information on the type= attribute usedon section definitions in the <configSections> section? Perhaps someone at MSDN could do some real homework, and write an in-depth article for MSDN Mag dealing with these classes, and the attributed programming model? Non-trivial, well-commentedexamples go a long way towardhelping developers in the trenches be productive.
The UrlConfigSection example is pretty poor; no comments, and unless I'm mistaken, there's no one place where any of the attributes are explained or discussed in any depth. They aren't even used in the cited example. And Ican certainly foresee a time when others besides myself might need access to the innerXML of a given tag in App.config... If MS expects anyone to use these classes for anything but the simplest retrieval of key/value pairs, they need to provide developers with a somewhat better grounding.
Lest you think I'm completely critical of these classes, I'll give MS this much: I like being able to encrypt specific sections of App.config using the RSAEncryptionProvider; very slick.
That said, I've programmed Microsoft operating systems for over 20 years, and this is the first time that I've had to post a question in a forum to figure out how to use an API Microsoft provided. The MSDN library itself is not the fine tool it used to be in years gone by.
Sincerely,
Duane T. Doutel
| | Duane Doutel Monday, May 29, 2006 3:44 PM | Hi Duane, Luke I'm facing the same problem and came across this post. I know it's been more than a year since you've replied, I was wondering what you found out by deserializing, and whether you found any solution for the problem. My requirement is to be able to put in an XML string as a setting which can be retrieved and sent to a web service call. Any help would be appreciated. Thanks & Regards, Prabin
| | Scorpion Prince Monday, August 20, 2007 1:17 PM | hi! i know its a little late. but i have a general solution to this problem available at http://devpinoy.org/blogs/jakelite/archive/2009/03/22/how-to-add-cdata-or-text-in-a-configurationelement.aspxit is non-obstrusive. it uses a declarative style of programming similar to the one used with the .Net 2.0 Configuration classes. To read configuration that looks like this?
<mailConfiguration server="localhost" port="25">
<mailTemplates>
<mailTemplate
name="template1"
sender="user@localhost">
<receivers>
<contactInfo
name="Jake Sta. Teresa"
email="jake@jakelite.com" />
</receivers>
<body>
<![CDATA[
Dear Sir,
This is a system generated message.
Thanks,
OMGWTFBBQ!!!
]]>
</body>
</mailTemplate>
</mailTemplates>
</mailConfiguration>
The class for the MailBodyElement would look like this.
public class MessageBodyElement
: CDataConfigurationElement {
[ConfigurationProperty("content", IsRequired = true, IsKey=true)]
[CDataConfigurationProperty]
public string Content
{
get { return (string)(base["content"]); }
set { base["content"] = value; }
}
}
Hope this helps!
- Proposed As Answer byjake.stateresa Monday, March 23, 2009 3:19 AM
-
| | jake.stateresa Monday, March 23, 2009 3:18 AM |
|