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?

10
  • 1
    -1: as you asked via comments, I have looked at your question. Maybe others will now do the same. Commented Dec 22, 2013 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... Commented Dec 22, 2013 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. Commented Dec 22, 2013 at 11:58
  • Solicit help by creating a good question, not by spamming other questions with comments that are not relevant to them. Commented Dec 22, 2013 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. Commented Dec 22, 2013 at 12:00

1 Answer 1

2
+50

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.

Sign up to request clarification or add additional context in comments.

7 Comments

Would work but looks more like a hack instead of fixing the namespace issue.
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.
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.
It sounds like you are not entirely happy with this solution. What is wrong with it?
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 <MyConfiguration>, 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...
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.