2

I have looked at the related question Intellisense for custom config section problem with namespaces which describes the same problem I have. Although the solution is not working for me.

I am pasting my entire solution in here, so others also can see how the desired feature is achieved. I have followed many tutorials on custom made configuration sections and how to achieve Intellisense in config files, but none are addressing the issue I am having.

I am getting a ConfigurationErrorException:

Unrecognized attribute 'xmlns'. Note that attribute names are case-sensitive.

I don't know hot to fix it.

My custom configuration section class:

namespace CustomConfigurationExample
{
    using System.Configuration;

    public class MyConfiguration : ConfigurationSection
    {
        [ConfigurationProperty("MyInstance")]
        public MyConfigurationElementCollection Configuration
        {
            get { return (MyConfigurationElementCollection)this["MyInstance"]; }
        }
    }

    public class MyConfigurationElement : ConfigurationElement
    {
        [ConfigurationProperty("MyEnums", IsKey = true, IsRequired = true)]
        public MyEnums MyEnums
        {
            get { return (MyEnums)base["MyEnums"]; }
        }

        [ConfigurationProperty("ConnectionAddress", IsKey = true, IsRequired = true)]
        public string ConnectionAddress
        {
            get { return (string)this["ConnectionAddress"]; }
        }

        [ConfigurationProperty("LoadBalancer", IsKey = true, IsRequired = true)]
        public bool LoadBalancer
        {
            get { return (bool)this["LoadBalancer"]; }
        }

    }

    public class MyConfigurationElementCollection : ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new MyConfigurationElement();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((MyConfigurationElement)element).MyEnums;
        }
    }
}

My Enums:

namespace CustomConfigurationExample
{
    public enum MyEnums
    {
        AB,
        CD,
        EF
    }
}

My App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="MyConfiguration" type="CustomConfigurationExample.MyConfiguration, CustomConfigurationExample" requirePermission="false" />
  </configSections>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <MyConfiguration xmlns="http://tempuri.org/MyConfiguration.xsd">
    <MyInstance>
      <add MyEnums="AB" LoadBalancer="true" ConnectionAddress="http://win.tendo.server:10305" />
    </MyInstance>
  </MyConfiguration>
</configuration>

My schema file:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="MyConfiguration"
    targetNamespace="http://tempuri.org/MyConfiguration.xsd"
    elementFormDefault="qualified"
    xmlns="http://tempuri.org/MyConfiguration.xsd"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="add">
    <xs:annotation>
      <xs:documentation>My configuration.</xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:attribute name="MyEnums" use="required" >
        <xs:annotation>
          <xs:documentation>MyEnums at blah blah</xs:documentation>
        </xs:annotation>
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:enumeration value="AB">
              <xs:annotation>
                <xs:documentation>AB</xs:documentation>
              </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="CD">
              <xs:annotation>
                <xs:documentation>CD</xs:documentation>
              </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="EF">
              <xs:annotation>
                <xs:documentation>EF</xs:documentation>
              </xs:annotation>
            </xs:enumeration>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="ConnectionAddress"></xs:attribute>
      <xs:attribute name="LoadBalancer">
        <xs:annotation>
          <xs:documentation>Loadbanlancer.</xs:documentation>
        </xs:annotation>
        <xs:simpleType>
          <xs:restriction base="xs:boolean">
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
    </xs:complexType>
  </xs:element>
</xs:schema>

...and at last my program.cs:

namespace CustomConfigurationExample
{
    using System.Collections;
    using System.Configuration;
    using System.Linq;

    class Program
    {
        static void Main(string[] args)
        {
            var mySettings = new ArrayList(((MyConfiguration)ConfigurationManager.GetSection("MyConfiguration")).Configuration).Cast<MyConfigurationElement>().Select(x => new { x.MyEnums, x.LoadBalancer, x.ConnectionAddress,  }).SingleOrDefault();
        }
    }
}

Now I have the intellisense in my configuration working all fine. But I get an exception when trying to map my settings when I run my program. I can remove the 'xmlns="http://tempuri.org/MyConfiguration.xsd"' part in my '<MyConfiguration xmlns="http://tempuri.org/MyConfiguration.xsd">' in my App.config file and add the location at its physical location under properties of my App.config in the 'Schemas' and the intellisense is working and mapping as well. But then the physical location is tied to my machine, and I want the location to be relative as the schema file is part of my VS solution. I prefer to reference the file relative in my solution.

What I am missing? I suspect that I need to decorate MyConfiguration class file with a namespace and schemalocation?

Community
  • 1
  • 1
codingjoe
  • 707
  • 5
  • 15
  • 32
  • 1
    -1: as you asked via comments, I have looked at your question. Maybe others will now do the same. – John Saunders Dec 22 '13 at 11:49
  • I have not asked via comments. I added this question yesterday, and started searching through previous asked questions on the same subject at stackoverflow. I have simply requested to look at my problem here. I really don't get why the vote downs instead of trying to help me. I am still looking for the fix. So instead of voting down my thread, please try to help me... – codingjoe Dec 22 '13 at 11:53
  • Can someone clarify why one gets vote downs? I have really been trying to fix this issue and decided to make a complete thread with detailed explanation and code so others can get help in the future. – codingjoe Dec 22 '13 at 11:58
  • Solicit help by creating a good question, not by spamming other questions with comments that are not relevant to them. – John Saunders Dec 22 '13 at 11:59
  • You spammed other questions to attract attention to this one. I recommend that you be careful what you ask for. You have certainly attracted _my_ attention, and may very well attract additional attention - the wrong kind. – John Saunders Dec 22 '13 at 12:00
  • Actually those comments are not spams. I could take the question from here and paste that into the commented thread instead, but then it would be a huge comment. This is question is closely related to those threads where I have requested to take a look at this thread. – codingjoe Dec 22 '13 at 12:01
  • That's now how we do things here. Your question needs to stand on its own. – John Saunders Dec 22 '13 at 12:01
  • I believe it does stand alone here. Please try to help me. – codingjoe Dec 22 '13 at 12:03
  • Then let it attract attention on it's own. Leave the other questions alone. I think I'll raise more attention by asking about this on [meta]. That will draw a _lot_ of attention. – John Saunders Dec 22 '13 at 12:05
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/43696/discussion-between-codingjoe-and-john-saunders) – codingjoe Dec 22 '13 at 12:06

1 Answers1

2

I found the problem in your code, and it ends up to be fairly simple. You need to add the xmlns tag to your MyConfiguration class like this:

public class MyConfiguration : ConfigurationSection
{
    [ConfigurationProperty("xmlns")]
    public string XmlNamespace
    {
        get
        {
            return (string)this["xmlns"];
        }
        set
        {
            this["xmlns"] = value;
        }
    }

    [ConfigurationProperty("MyInstance")]
    public MyConfigurationElementCollection Configuration
    {
        get { return (MyConfigurationElementCollection)this["MyInstance"]; }
    }
}

Then the ConfigurationManager knows how to read this.

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
  • Would work but looks more like a hack instead of fixing the namespace issue. – codingjoe Dec 24 '13 at 00:40
  • Well. It isn't. It all makes sense, let me explain. The XML / XSD / Intellisense integration knows how to read XML, including the 'preserved' keyword xmlns. The ConfigurationManager class on the other hand is not that smart. It just reads every attribute and element in a XML fragment, including the xmlns keyword, meaning it will complain when not finding a property in your class that maps to it. – Patrick Hofman Dec 24 '13 at 06:42
  • Looking at the amount of time I have spent trying to fix this, and trying different approaches with deserializing the configuration settings instead. I am going to accept this answer. I actually also found this solution approach somewhere when I googled a couple of days ago. – codingjoe Dec 24 '13 at 11:02
  • It sounds like you are not entirely happy with this solution. What is wrong with it? – Patrick Hofman Dec 24 '13 at 14:25
  • Firstly, I removed the set property, as I am not going to set it, so that is a minor thing. Secondly I expected the cast of my settings would ignore my xml namespace, or a solution where I don't need to add the xmlns='' in my , and instead have my schema be a part of the default namespace. I can be wrong, but if my schema file can be in my default application namespace, then I would not need to add the xmlns='' in my MyConfiguration tag. Or am I completely wrong? Happy to see others to jump in... – codingjoe Dec 24 '13 at 15:40
  • I think it is like I said before: an 'not so smart' implementation of the ConfigurationManager. I guess there can be reasons you want to include this (when xmlns as an attribute does matter), so I think that's why Microsoft didn't filter it out. When you use this model a lot you can opt for a custom class that by default implements this property, but that is more of a hack. – Patrick Hofman Dec 24 '13 at 15:44
  • Do you need more info or help on this one? – Patrick Hofman Dec 25 '13 at 22:10