views:

186

answers:

1

I have the following code

var section = new CustomConfigurationSection();
section.SectionInformation.Type = "System.Configuration.NameValueFileSectionHandler";
section.SectionInformation.SetRawXml(sectionXml);
configuration.Sections.Add(sectionName, section);

last line of which throws:

ConfigurationErrorsException An error occurred executing the configuration section handler for monitor.

with the inner exception:

Unrecognized element 'screens'. (line 1) (line 1)

Definition of CustomConfigurationSection:

public class CustomConfigurationSection: ConfigurationSection
{
    public CustomConfigurationSection()
    {
    }
}

configuration is an instance of a custom class, which has a property named Sections, that have the type 'ConfigurationSectionCollection'.

And the incoming xml in sectionXml is:

<monitor>
  <screens>
    <screen>
      <regions>
        <region>
          <labelCoordinates />
          <startupApplication>Internet</startupApplication>
          <color />
          <width>426</width>
          <height>266</height>
          <x1>0</x1>
          <x2>0</x2>
          <y1>0</y1>
          <y2>0</y2>
        </region>
      </regions>
      <height>800</height>
      <width>1280</width>
    </screen>
    <screen>
      <regions />
      <height>0</height>
      <width>0</width>
    </screen>
  </screens>
</monitor>

How can I get this to work?

A: 

After looking at your example one reason I can see that it won't work is you are using the NameValueFileSectionHandler. If I remember correctly this only allows the following syntax:

<YourSectionName>
  <add key="monitor.region.x" value="0"/>
<YourSectionName>

Based on the xml you are wanting to use you probably need to fully implement the config section classes. So you would have something like the following:

class ServiceResponseSection : ConfigurationSection
{
    [ConfigurationProperty("ServiceResponses")]
    [ConfigurationCollection(typeof(ServiceResponse), AddItemName = "addServiceResponse", RemoveItemName = "removeServiceResponse", ClearItemsName = "clearServiceResponses")]
    public ServiceResponses ServiceResponses
    {
        get { return this["ServiceResponses"] as ServiceResponses; }
    }

}

public class ServiceResponses : ConfigurationElementCollection
{
    public override ConfigurationElementCollectionType CollectionType
    {
        get
        {
            return ConfigurationElementCollectionType.AddRemoveClearMap;
        }
    }

    public ServiceResponse this[int index]
    {
        get
        {
            return (ServiceResponse)this.BaseGet(index);
        }
        set
        {
            if (this.BaseGet(index) != null)
            {
                this.BaseRemoveAt(index);
            }
            this.BaseAdd(index, value);
        }
    }

    public new ServiceResponse this[string responseString]
    {
        get
        {
            return (ServiceResponse)this.BaseGet(responseString);
        }
        set
        {
            if (this.BaseGet(responseString) != null)
            {
                this.BaseRemoveAt(this.BaseIndexOf(this.BaseGet(responseString)));
            }
            this.BaseAdd(value);
        }
    }

    public void Add(ServiceResponse ServiceResponse)
    {
        this.BaseAdd(ServiceResponse);
    }

    public void Clear()
    {
        this.BaseClear();
    }

    protected override ConfigurationElement CreateNewElement()
    {
        return new ServiceResponse();
    }

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((ServiceResponse)element).ResponseString;
    }

    public void Remove(ServiceResponse element)
    {
        BaseRemove(element.ResponseString);
    }

    public void Remove(string responseString)
    {
        BaseRemove(responseString);
    }

    public void RemoveAt(int index)
    {
        BaseRemoveAt(index);
    }

}

public class ServiceResponse : ConfigurationElement
{
    private int m_tryCount;

    public ServiceResponse()
    {
        this.m_tryCount = 0;
    }

    [ConfigurationProperty("responseString")]
    public string ResponseString
    {
        get { return (String)this["responseString"]; }
        set { this["responseString"] = value; }
    }

    [ConfigurationProperty("matchWholeString")]
    public bool MatchWholeString
    {
        get
        {
            return (bool)this["matchWholeString"];
        }
        set
        {
            this["matchWholeString"] = value.ToString();
        }
    }

    [ConfigurationProperty("retryCount")]
    public int RetryCount
    {
        get
        {
            return (int)this["retryCount"];
        }
        set
        {
            this["retryCount"] = value.ToString();
        }
    }

    [ConfigurationProperty("failsProcess")]
    public bool FailsProcess
    {
        get
        {
            return (bool)this["failsProcess"];
        }
        set
        {
            this["failsProcess"] = value.ToString();
        }
    }

    public int TryCount
    {
        get { return this.m_tryCount; }
        set { this.m_tryCount = value; }
    }

    public void Reset()
    {
        this.m_tryCount = 0;
    }

}

This would then use xml like the following:

    <ServiceResponseList>
    <ServiceResponses>
        <clearServiceResponses/>
        <addServiceResponse responseString="API Server Login Error" matchWholeString="false" retryCount="5" failsProcess="false"/>
    </ServiceResponses>
</ServiceResponseList>

The main point is that I am using a collection (which you have in your example, actually a couple of them). Within that collection is an object that I am representing. So to get it to parse the xml you have you would have to make a section handler to match what you are using.

Based on my example you would probably want to change your xml to something along the line of:

<monitor>
  <screens>
    <screen height="800" width="1280">
      <regions>
         <region startupApplication="Internet" width="426" height="266" x1="0" x2="0" y1="0" y2="0"/>
     </regions>
   </screen>
  </screens>
</monitor>

You could then use classes similar to my example. Although you could probably get what you are wanting but you will need to use other configuration items to get it to work that way.

Hope that helps.

Joshua Cauble