Reeta
Reeta

Reputation: 33

Defining duplicate key values in custom config section app.config

I have a custom configuration section i.e. RegisterCompanies.But the key name has same value for two entries.when i try to read the config section im getting ConfigurationerrorException saying Key element xxx have already been added.Can anybody tell me how to add duplicate keys in the custom configuration. Following is the config section i want to add to my app.config ..

<RegisterCompanies>
    <Companies>
      <Company name="Tata Motors" code="Tata"/>
      <Company name="Tata Motors" code="Honda"/>
    </Companies>
  </RegisterCompanies>

Upvotes: 1

Views: 3209

Answers (4)

brainboost
brainboost

Reputation: 379

If your config structure is like this

<RegisterCompanies>
    <Companies>
      <Company name="Tata Motors">
        <Codes>
          <Code name="Tata" />
          <Code name="Honda" />
        </Codes>
      </Company>
    </Companies>
  </RegisterCompanies>

then you need the following section handler

public class CompaniesConfigurationHandler : IConfigurationSectionHandler
{
    public object Create(object parent, object configContext, XmlNode section)
    {
        var config = new CompaniesConfiguration();
        XmlNode xCompanies = section.SelectSingleNode("Companies");
        if (xCompanies == null)
            throw new ConfigurationErrorsException("Companies node not found");
        config.Companies = CreateCompanies(xCompanies);
        return config;
    }

    private static CompanyConfiguration[] CreateCompanies(XmlNode xCompanies)
    {
        var nodes = xCompanies.SelectNodes("Company");
        return nodes == null ?
                   new CompanyConfiguration[0]
                   : nodes.Cast<XmlNode>().Select(ReadCompany).ToArray();
    }

    private static CompanyConfiguration ReadCompany(XmlNode xCompany)
    {
        var company = new CompanyConfiguration();
        if (!((XmlElement) xCompany).HasAttribute("name"))
            throw new ConfigurationErrorsException("Company node must have name attribute", xCompany);
        company.Name = ((XmlElement) xCompany).GetAttribute("name");
        var codes = (XmlElement)xCompany.SelectSingleNode("Codes");
        company.Codes = ReadCodes(codes);
        return company;
    }

    private static string[] ReadCodes(XmlNode xElement)
    {
        XmlNodeList xItems = xElement.SelectNodes("Code");
        return xItems == null ?
                                  new string[0]
                   : xItems
                         .Cast<XmlElement>()
                         .Where(xItem => xItem.HasAttribute("name"))
                         .Select(xItem => xItem.GetAttribute("name"))
                         .ToArray();
    }
}

public class CompanyConfiguration
{
    public string Name { get; set; }
    public string[] Codes { get; set; }
}

public class CompaniesConfiguration
{
    public CompanyConfiguration[] Companies { get; set; }
}

easy-peasy.

Upvotes: 1

Fischermaen
Fischermaen

Reputation: 12458

I would prefer to change the data structure, so there can be mode "Code" entries per company like this way

   <RegisterCompanies>
    <Companies>
      <Company name="Tata Motors"/>
      <Codes>
        <Code name="Tata" />
        <Code name="Honda" />
      </Codes>
    </Companies>
  </RegisterCompanies>

Upvotes: 0

BigMike
BigMike

Reputation: 6873

a nasty way could be swapping key and code in your xml

<RegisterCompanies>
    <Companies>
      <Company code="Tata Motors" name="Tata"/>
      <Company code="Tata Motors" name="Honda"/>
    </Companies>
  </RegisterCompanies>

And then reparse the resulting collection in order to fix things, but as stated before, this is a VEERY NASTY way.

Since you're defining your own block of configuration, you should be able to provide the mapping to a different collection object (one accepting the same key several ways). I think I have something similar, which registers the section file parser/renderer for an ASP.NET application. Will look if I can found it ASAP.

Initial details and a quite complete sample can be found here

Regards

Upvotes: 0

Marco
Marco

Reputation: 57573

I think you should do this way:

<RegisterCompanies>
    <Companies>
      <Company name="Tata Motors">
          <Code name="Tata"/>
          <Code name="Honda"/>
      </Company>
    </Companies>
</RegisterCompanies>

Upvotes: 4

Related Questions