1

Hopefully, I can present this problem to the brain trust of this site and someone will see my mistake.

I am working on a project where email text needs to be "mail merged" with information found in the properties of various internal classes. A typical symbol found in the email text might look like "{member name}, {mobile phone}, etc."

I would like to define the symbols and the classes they are found in using a ConfigurationSection in web.config. Here is my proposed configuration section:

<EmailSymbols>
    <SymbolClasses>

        <SymbolClass name="OHMember">
            <Symbol name="Member Name" template="{0} {1}">
                <add index="0" value="SMFirstName" />
                <add index="1" value="SMLastName" />
            </Symbol>
            <Symbol name="Phone" template="{0}">
                <add index="0" value="SMPhone" />
            </Symbol>
        </SymbolClass>

        <SymbolClass name="Form">
            <Symbol name="Contact Name" dataname="ContactName" />
        </SymbolClass>

    </SymbolClasses>
</EmailSymbols>

...and the code that I am trying to parse it with:

public class EmailSymbols : ConfigurationSection {

    [ConfigurationProperty("SymbolClasses", IsRequired = true)]
    public SymbolClassCollection SymbolClasses {
        get {
            return this["SymbolClasses"] as SymbolClassCollection;
        }
    }
}

[ConfigurationCollection(typeof(SymbolClass), AddItemName = "SymbolClass")]
public class SymbolClassCollection : ConfigurationElementCollection {

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

    protected override object GetElementKey(ConfigurationElement element) {
        return ((SymbolClass)element).Name;
    }
}

[ConfigurationCollection(typeof(Symbol), AddItemName = "Symbol")]
public class SymbolClass : ConfigurationElementCollection {

    [ConfigurationProperty("name", IsRequired = true, IsKey = true)]
    public String Name {
        get {
            return this["name"] as String;
        }
    }

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

    protected override object GetElementKey(ConfigurationElement element) {
        return ((Symbol)element).Name;
    }
}

[ConfigurationCollection(typeof(TemplateValue), AddItemName = "add")]
public class Symbol : ConfigurationElementCollection {

    [ConfigurationProperty("name", IsRequired = true, IsKey = true)]
    public String Name {
        get {
            return this["name"] as String;
        }
    }

    [ConfigurationProperty("template", IsRequired = false)]
    public String Template {
        get {
            return this["template"] as String;
        }
    }

    [ConfigurationProperty("dataname", IsRequired = false)]
    public String DataName {
        get {
            return this["dataname"] as String;
        }
    }

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

    protected override object GetElementKey(ConfigurationElement element) {
        return ((TemplateValue)element).Index;
    }
}

public class TemplateValue : ConfigurationElement {

    [ConfigurationProperty("index", IsRequired = false, IsKey = true)]
    public Int32 Index {
        get {
            return this["index"] == null ? -1 : Convert.ToInt32(this["index"]);
        }
    }

    [ConfigurationProperty("value", IsRequired = false)]
    public String Value {
        get {
            return this["value"] as String;
        }
    }
}

When I parse the section with this statement: symbols = ConfigurationManager.GetSection("EmailSymbols") as EmailSymbols;

I receive this error message: "Unrecognized element 'Symbol'."

This is simply an area of .NET that I don't know my way around. Any help that anyone could give would be most appreciated.

Does my XML definition make sense and is it in the correct form? I want a collection of SymbolClass, each containing a collection of Symbol, each containing a collection of TemplateValue.

Again, thanks for your help.

Best Regards, Jimmy

JConnell
  • 93
  • 1
  • 4
  • did you register the section up at the top of the config file? http://msdn.microsoft.com/en-us/library/2tw134k3.aspx – Darren Kopp Oct 19 '13 at 02:40
  • I did. It parses until it gets to , then I get an exception with error: "Unrecognized element 'Symbol'." I've declared "Symbol" using "AddItemName". If I add Symbol as a ConfigurationProperty, the parser will then recognize "Symbol", but then tell me that "Symbol" can only be used once. – JConnell Oct 21 '13 at 02:04
  • 1
    it's a duplicate. There's a great answer here : http://stackoverflow.com/questions/5661544/correct-implementation-of-a-custom-config-section-with-nested-collections – klev Feb 08 '16 at 09:22

1 Answers1

1

You could try to override the Init() method of the SymbolClass class:

protected override void Init()
{
    base.Init();
    this.AddElementName = "Symbol";
}

You an also remove [ConfigurationCollection(typeof(SymbolClass), AddItemName = "SymbolClass")] and the others like it from above the class declarations as their not doing anything.

ferro
  • 155
  • 1
  • 1
  • 9