Banner

Simple Key-Value Sitefinity Configuration with NameValueCollection Property

Jun 27, 2017

Sitefinity allows you to easily create a custom configuration setting for storing and managing properties for your site. For the most part, you simply need to inherit from ConfigSection and add your properties. Once registered your settings will be automatically added to the backend Sitefinity Configuration page (Administration > Settings > Advanced).

The documentation for this feature explains that there are several different types of properties supported, including simple types (like bool, string, etc.), as well as custom types that you can create by inheriting from ConfigElement and even collections for managing those custom types.

However, one additional property type that is supported for a custom config section is a regular NameValueCollection property. Here is the excerpt from the code sample provided for this property:

[ConfigurationProperty( "parameters" )]
    public NameValueCollection Parameters
    {
        get
        {
            return ( NameValueCollection )this[ "parameters" ];
        }
        set
        {
            this[ "parameters" ] = value;
        }
    }

I attempted to create a simple config section to store a map of names to Urls (for a custom redirect widget), creating a simple config with a single NameValueCollection property:
[ObjectInfo(Title = "GeoRedirectConfig Title", Description = "GeoRedirectConfig Description")]
public class GeoRedirectConfig : ConfigSection
{
    [ConfigurationProperty("redirects")]
    public NameValueCollection Redirects
    {
        get
        {
            return (NameValueCollection) this["redirects"];
        }
        set
        {
            this["redirects"] = value;
        }
    }
}

However, when I ran the site and attempted to save a setting to this property, I got this error:
sitefinity-config-name-value-parameter-error-300x103

Now, I had initially created this class by copying the sample above, and so I thought perhaps Sitefinity was caching a build with that property or somehow not updating with my changes. But changing it back to the exact original sample code resolved the issue and it worked as expected.

It turns out, while the documentation explains that you can only have one such NameValueCollection property on your config section, it does not explain that the internal property name apparently must be the exact name “parameters” as they use in the example.

Indeed this was verified by looking in Reflector to see the code sent when you save changes:

// ...
 
  if ((collection != null) && (collection is NameValueCollection))
  {
      // ...
       
      element.SetParameter(str, str2);
       
      // ...
  }
 
  // ...

If the property is of type NameValueCollection, it uses the SetParameter method, which then does a lookup based on the exact string “parameters”:
public virtual void SetParameter(string key, string value)
{
    ConfigProperty property;
    if ((!this.Properties.TryGetValue("parameters", out property) || (property == null)) || !typeof(NameValueCollection).IsAssignableFrom(property.Type))
    {
        throw new InvalidOperationException($"'{base.GetType().FullName}' does not have '{"parameters"}' property of type '{typeof(NameValueCollection).FullName}'");
    }
    NameValueCollection values = this[property] as NameValueCollection;
    if (values != null)
    {
        values[key] = value;
    }
}

So, to finally resolve this, but still keep the name I want for the property, I kept the internal “parameters” name and simply renamed the property:

[ConfigurationProperty("parameters")]
public NameValueCollection Redirects
{
    get
    {
        return (NameValueCollection) this["parameters"];
    }
    set
    {
        this["parameters"] = value;
    }
}
And at last the property works as expected:
sitefinity-config-key-value-pair

So if you want a simple key-value pair config in your Sitefinity site, it’s a simple task, just remember to name it appropriately!

As always, I hope this is helpful, and thanks for reading!

Load more comments
comment-avatar

Copyright © 2017 Alain "Lino" Tadros