I am trying to create a custom config section for storing api settings by region. This is for a asp.net web api.
However I am unable to get my custom config section to work. When I run the unit test it says:
Message: System.Configuration.ConfigurationErrorsException : Unrecognized attribute 'id'".
public class MyApiConfigSection : ConfigurationSection
{
public static Lazy<MyApiConfigSection> Configuration = new Lazy<MyApiConfigSection>(() =>
ConfigurationManager.GetSection("myApi/myApi.regions") as MyApiConfigSection);
[ConfigurationProperty("myApiSettings")]
public MyApiElement MyApiSettings
{
get
{
return (MyApiElement)this["myApiSettings"];
}
set
{
this["myApiSettings"] = value;
}
}
}
public class MyApiElement : ConfigurationElement
{
[ConfigurationProperty("apiVersions", IsDefaultCollection = true)]
[ConfigurationCollection(typeof(ApiVersionsCollection))]
public ApiVersionsCollection ApiVersions
{
get
{
ApiVersionsCollection gtVersions =
(ApiVersionsCollection)base["apiVersions"];
return gtVersions;
}
set
{
ApiVersionsCollection apiVersions = value;
}
}
}
public class ApiVersionsCollection : ConfigurationElementCollection
{
public ApiVersionsCollection() { }
protected override ConfigurationElement CreateNewElement()
{
return new ApiVersionElement();
}
protected override Object GetElementKey(ConfigurationElement element)
{
return ((ApiVersionElement)element).Id;
}
public ApiVersionElement this[int index]
{
get
{
return (ApiVersionElement)BaseGet(index);
}
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}
new public ApiVersionElement this[string name]
{
get
{
return (ApiVersionElement)BaseGet(name);
}
}
}
public class ApiVersionElement : ConfigurationElement
{
public ApiVersionElement() { }
public ApiVersionElement(string id, string apiKey, RegionUrlsCollection regionUrls)
{
this.Id = id;
this.ApiKey = apiKey;
this.RegionUrls = regionUrls;
}
[ConfigurationProperty("id", IsRequired = true, IsKey = true)]
public string Id
{
get { return this["id"] as string; }
set { this["id"] = value; }
}
[ConfigurationProperty("apiKey", IsRequired = true)]
public string ApiKey
{
get { return (string)this["apiKey"]; }
set { this["apiKey"] = value; }
}
[ConfigurationProperty("regionUrls", IsDefaultCollection = true)]
[ConfigurationCollection(typeof(RegionUrlsCollection))]
public RegionUrlsCollection RegionUrls
{
get
{
RegionUrlsCollection regionUrls =
(RegionUrlsCollection)base["regionUrls"];
return regionUrls;
}
set
{
RegionUrlsCollection regionUrls = value;
}
}
}
public class RegionUrlsCollection : ConfigurationElementCollection
{
public RegionUrlsCollection() { }
protected override ConfigurationElement CreateNewElement()
{
return new RegionElement();
}
protected override Object GetElementKey(ConfigurationElement element)
{
return ((RegionElement)element).Name;
}
public RegionElement this[int index]
{
get
{
return (RegionElement)BaseGet(index);
}
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}
new public RegionElement this[string name]
{
get
{
return (RegionElement)BaseGet(name);
}
}
}
public class RegionElement : ConfigurationElement
{
public RegionElement() { }
public RegionElement(string name, string url)
{
this.Name = name;
this.Url = url;
}
[ConfigurationProperty("name", IsRequired = true, IsKey = true)]
public string Name
{
get { return (string)this["name"]; }
set { this["name"] = value; }
}
[ConfigurationProperty("url", IsRequired = true)]
public string Url
{
get { return (string)this["url"]; }
set { this["url"] = value; }
}
}
The config section in the App.config
is given below:
Other Similar sections are loading correctly -the only difference is that there are 2 nested collections here.
<myApi>
<myApi.regions>
<myApiSettings>
<apiVersions id="1" apiKey="sample_api_key_1">
<regionUrls>
<region name="amer" url="" />
<region name="apac" url="" />
<region name="emea" url="" />
</regionUrls>
</apiVersions>
<apiVersions id="2" apiKey="sample_api_key_2">
<regionUrls>
<region name="amer" url="" />
<region name="apac" url="" />
<region name="emea" url="" />
</regionUrls>
</apiVersions>
</myApiSettings>
</myApi.regions>
</myApi>