It is with a heavy heart that I must report on a change that has been made in the .NET Framework 1.1 SP1, which is undocumented (based on my recent trawling of Google and MSDN). This has unfortunately caused me much grief due to a Technical “Maintenance” team that does no maintenance at all and has still not installed SP1! But don't worry... I just installed it for them... as usual.
Here's the issue I had. I have a simple Windows Forms application that defines a custom configSection in the app.config file. When I run this on a computer with .NET Framework 1.1 SP1 all is fine. But it throws an Exception when calling the ConfigurationSettings.GetConfig() method on a computer that does not have .NET Framework 1.1 SP1. Fair enough... I should've checked earlier that the other computer had SP1 installed, but I think that this should at least be documented in the List of bugs that are fixed in the .NET Framework 1.1 Service Pack 1 (SP1). If I've just missed it, then please correct me! I don't want to blame anyone unnecessarily.
Here's a bit of a sample for you to see what happens:
Step 1: Create a form with a single button called “btnGetConfig”. Add the following code the Click event of the button:
Hashtable config = (Hashtable)ConfigurationSettings.GetConfig("customSection");
MessageBox.Show(config["Name"].ToString());
Step 2: Now add an app.config file with the following contents:
<
configuration>
<configSections>
<section name="customSection" type="GetConfigDemoApp.CustomSectionHandler, GetConfigDemoApp" />
</configSections>
<customSection>
<field name="Name" text="Text" />
</customSection>
</configuration>
Step 3: Now add a new class called CustomSectionHandler, and have it implement the IConfigurationSectionHandler interface. In the Create method, add the following code:
Hashtable customObjects = new Hashtable();
foreach (XmlNode node in section.ChildNodes)
{
string name = node.Attributes["name"].Value;
string text = node.Attributes["text"].Value;
customObjects.Add(name, text);
}
return customObjects;
Step 4: Now you're ready to go! Run this app on a computer with SP1 and all is good. Then run it on a computer without SP1 and it gives the following exception:
System.Configuration.ConfigurationException: Exception in configuration section handler (C:\Stuart\GetConfigDemo\GetConfigDemoApp\bin\Debug\GetConfigDemoApp.exe.config line 7) ---> System.NullReferenceException: Object reference not set to an instance of an object.
at GetConfigDemoApp.CustomSectionHandler.Create(Object parent, Object configContext, XmlNode section) in C:\Stuart\GetConfigDemo\GetConfigDemoApp\CustomSectionHandler.cs:line 24
at System.Configuration.ConfigurationRecord.EvaluateRecursive(IConfigurationSectionHandler factory, Object config, String[] keys, Int32 iKey, XmlTextReader reader)
--- End of inner exception stack trace ---
at System.Configuration.ConfigurationRecord.EvaluateRecursive(IConfigurationSectionHandler factory, Object config, String[] keys, Int32 iKey, XmlTextReader reader)
at System.Configuration.ConfigurationRecord.Evaluate(String configKey)
at System.Configuration.ConfigurationRecord.ResolveConfig(String configKey)
at System.Configuration.ConfigurationRecord.GetConfig(String configKey)
at System.Configuration.DefaultConfigurationSystem.System.Configuration.IConfigurationSystem.GetConfig(String configKey)
at System.Configuration.ConfigurationSettings.GetConfig(String sectionName)
at GetConfigDemoApp.Form1.btnGetConfig_Click(Object sender, EventArgs e) in c:\stuart\getconfigdemo\getconfigdemoapp\form1.cs:line 90
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Alas... I have no ideas?!?! If anyone knows why this happens, please let me know! Of course, it is using different versions of the .NET Framework so I can't really expect it to work. But if it really isn't documented anywhere... why not???
The example I've given here is truly over-simplistic, but it drives to the heart of the problem without unnecessarily cluttering the demo.