1

UPDATE: Custom Configs are freaking HARD! >.< While I've learned some things about XML; evidently it's impossible to store CDATA in an element, so I've rephrased this question to fit the modified structure. Please ask me any questions for clarity. I've been working on this issue for around a month off and on and keep running into various issues.

I've been follow the MSDN example in the article referenced below, but I'm have trouble applying the concept to my case. My project is a VB.NET 4.0 Web Application in VS2010, but answers in C# are alright as well (as long as the solution will work in VB). :) Here's the relevant code:

Call:

Dim conf As ApiSection = CType(ConfigurationManager.GetSection("remoteServiceApi/site"), ApiSection)

Exception (ConfigurationErrorsException)

The element <site> may only appear once in this section.

Please note the following relevant code...

Schema:

<xs:element name="ApiSection">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="site" id="environment" nillable="false" maxOccurs="unbounded">
                <xs:complexType>
                    <xs:attribute name="environment" use="required">
                        <xs:simpleType>
                            <xs:restriction base="xs:string">
                                <xs:enumeration value="Production"></xs:enumeration>
                                <xs:enumeration value="Sandbox"></xs:enumeration>
                            </xs:restriction>
                        </xs:simpleType>
                    </xs:attribute>
                    <xs:attribute name="APIKey" type="xs:string" use="required" />
                    <xs:attribute name="APIUsername" type="xs:string" use="required" />
                    <xs:attribute name="APIPassword" type="xs:string" use="required" />
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>
</xs:element>

Even though I added and activated the above in the schema set for the web.config file, it does not seem to be actually working. :( Could this be the issue?

Web.Config:

<configSections>
    <sectionGroup name="remoteServiceApi">
        <section name="site" type="RemoteServiceApi.ApiSection" />
    </sectionGroup>
</configSections>
<remoteServiceApi environment="Sandbox">
    <site environment="Sandbox"
        APIKey="reallyLongHashKeyDev"
        APIUsername="samplejoe"
        APIPassword="joespass" />
    <site environment="Production"
        APIKey="reallyLongHashKeyProd"
        APIUsername="samplejoe"
        APIPassword="joespass" />
</remoteServiceApi>

Class File:

Imports System.Configuration

Namespace RemoteServiceApi
    Public Class ApiSection
        Inherits ConfigurationSection

        <ConfigurationProperty("site", IsRequired:=True)> _
        Public Property site() As SiteElement
            Get
                Return CType(Me("site"), SiteElement)
            End Get
            Set(value As SiteElement)
                Me("site") = value
            End Set
        End Property
    End Class

    Public Class SiteElement
        Inherits ConfigurationElement

        <ConfigurationProperty("Environment", DefaultValue:="Sandbox", IsRequired:=True)> _
        Public Property Environment() As String
            Get
                Return CStr(Me("Environment"))
            End Get
            Set(value As String)
                Me("Environment") = value
            End Set
        End Property

        <ConfigurationProperty("APIKey", IsRequired:=True)> _
        Public ReadOnly Property APIKey() As String
            Get
                Return CStr(Me("APIKey"))
            End Get
        End Property

        <ConfigurationProperty("APIUsername", IsRequired:=True)> _
        Public ReadOnly Property APIUsername() As String
            Get
                Return CStr(Me("APIUsername"))
            End Get
        End Property

        <ConfigurationProperty("APIPassword", IsRequired:=True)> _
        Public ReadOnly Property APIPassword() As String
            Get
                Return CStr(Me("APIPassword"))
            End Get
        End Property
    End Class

    Public Enum Environment
        Production
        Sandbox
    End Enum
End Namespace

References I'm using as a guide:

Chiramisu
  • 4,687
  • 7
  • 47
  • 77

1 Answers1

1

You need to make the Site element a collection (based upon your posted Web.config). Try something like this (in C#, sorry):

[ConfigurationCollection(typeof(SiteElement)[
public class SiteElementCollection : ConfigurationElementCollection

    public SiteElement this[string name]
    {
        get
        {
            return (SiteElement)base.BaseGet(name);
        }
    }

    public SiteElement this[int index]
    {
        get
        {
            return (SiteElement)base.BaseGet(index);
        }
    }

    public override ConfigurationElement CreateNewElement()
    {
        return new SiteElement();
    }

    public override object GetElementKey(ConfigurationElement element)
    {
        return ((SiteElement)element).AddressKey;
    }

This class will wrap the SiteElement allowing you to have multiple instances of the element.

The next part I'm not 100% sure of, because I've never used a ConfigurationElementCollection immediately under the section, but you'll need to reference the collection.

As an example (which doesn't quite fit what you're trying to do, but will hopefully fit), assume you had a section name Sites under the section group. You could do this:

public SiteElementCollection Sites
{
    get
    {
        return (SiteElementCollection)base["site"];
    }
}

I hope this gives you at least a direction to follow. The key here is to use the ConfigurationElementCollection when you need to have multiple instances of a given element.

Tim
  • 28,212
  • 8
  • 63
  • 76