Managing Custom Configuration Options for a SharePoint Application

David Mann, Mann Software

December 2009

Applies to: Windows SharePoint Services 3.0, Microsoft Office SharePoint Server 2007

Summary: Many applications require some type of external configuration information. SharePoint offers developers many options for storing custom configurations settings outside of the application itself. These options include storing inside the web.config file on front-end Web servers, using the property bag on various Windows SharePoint Services objects, storing configuration data within SharePoint lists, or by using the hierarchical object storage. (13 printed pages)

Contents

  • Goal: Storing Application Configuration Settings Outside of an Application

  • Standard ASP.NET Configuration Options (Not Recommended)Standard ASP.NET Configuration Options (Not Recommended)

  • SharePoint Configuration Options (Recommended)

  • Storing Sensitive Information

  • Performance

  • Recommendations

  • Conclusion

  • Additional Resources

Goal: Storing Application Configuration Settings Outside of an Application

In general, the goal is to avoid hard coding any values in source code that could reasonably be expected to change during the lifetime of the application. Furthermore, those values should be stored in such a way that they can be accessed and changed without developer involvement. It is helpful if the settings can be easily changed by an administrator by using a simple, intuitive interface. At the far end of the spectrum, some of the advanced functionality that could be supported includes:

  • Password protected storage

  • Encryption

  • Versioning of values and the ability to roll back to previous versions

  • Approval for value changes

The typical example of a configuration setting that needs to be persisted somewhere is a database connection string. Other examples include:

  • Server names

  • List names

  • URLs

  • Email addresses

  • Approval thresholds

While all of these values are strings, it is important to note that settings can be as simple as a scalar value - int, char, float, etc. - a slightly more complex string value such as those shown above, an object stored as a serialized XML string, or a binary object; it all depends on the needs of the application.

The recommendations made here are especially relevant to any new applications you are building in SharePoint. If an application is being converted from an ASP.NET application to a SharePoint application, a determination should be made whether the option chosen for the previous version of the application is appropriate. In some cases it may be the best choice simply because the existing logic can be reused. This is described below.

Although there are standard ASP.NET options available to manage custom configurations that developers are likely familiar with, such as using the standard <AppSettings> section in a Web application's web.config file or the option to store your values in a custom settings store (either file based or in a database), neither of these choices are recommended for use in SharePoint. They are mentioned here only because there can be value in considering them in cases where you are converting an application from a standard ASP.NET application to a SharePoint application and the original ASP.NET application has made significant use of one of these options. In this case only, the benefit of being able to reuse logic or user interfaces and also reduce training requirements may be enough reason to warrant their use in a SharePoint application. However, since they are not recommended, these options are not discussed in this paper.

There are much better SharePoint-specific options available to help SharePoint developers manage custom configurations. These are discussed in depth in the following sections.

Options for storing application configurations outside of the application itself include storing the configuration settings inside the web.config file, within property bags or inside of SharePoint lists, or within the hierarchical object storage.

SharePoint Web.config Support

In these option, configuration settings are stored inside the web.config file on each front-end Web server. The significant difference when using this option is that SharePoint introduces some functionality that can eliminate issues that can arise when you have multiple servers running and you need to introduce new servers into the environment after your application is deployed.

The SPWebConfigModification class was introduced in Windows SharePoint Services 3.0 and Office SharePoint Server 2007 and it offers developers a framework for adding values to the web.config file on the front-end Web servers. The benefit of this approach is that SharePoint handles the work of introducing these changes to all front-end Web servers in the server farm - even if new servers are added to the farm after the change was made. This represents a huge benefit for developers, and is the primary reason that storing settings in the web.config is an excellent option for SharePoint applications.

Pros/Cons

Benefits

  • Easy - A single line of code to read configuration values.A few extra lines of code are required to write values by using the SPWebConfigModification class, but overall, an easy approach.

  • Performance Improvements - The entire contents of the web.config file are stored in memory, which allows it to read faster when retrieving setting values.However, you do not want to store large values or excessively large numbers of values or this benefit can become a drawback by increasing memory usage.

  • Multiserver issues handled easily - The SPWebConfigModification class in the SharePoint object model handles all of the multiserver issues.

  1. Drawbacks
  • Performance Degradation - Changes to the web.config file cause the Internet Information Services (IIS) application pool to reset, which means that all JIT-compiled code must be recompiled and cached. This impacts performance significantly for every new page load after the change is made.

  • No advanced capabilities - There are no default capabilities to review, approve, version, audit or roll back changes that are made to the web.config file. Changes are made directly to the file and are live and in production immediately upon saving the file.

  • Difficult to store variations - All settings are essentially independent of all other settings, so it can be difficult to store variations of a single setting, such as per-Locale, per-User, and so on.

  • Backup/Restore - You must make sure that your web.config file is covered in your backup/restore plans.

  • Scope - Settings stored by using this option are scoped at the Web application level, which may not be granular enough for your needs, or conversely, may be too global.

Sample Code

Adding an entry to the web.config by using the SPWebConfigModification class is a little more complicated than in ASP.NET. In the following sample:

  • webApp is the Web application whose web.config should be modified.

  • Name is the name of the modification. It is needed to be able to remove the entry. Ex: add[@name='UniqueName'].

  • XPath is the canonical path to the location of the entry in the web.config file. Example: configuration/AppSettings

  • UniqueOwnerId is the identifier for the parent of this entry. It is required to be able to remove each entry properly. Multiple web.config entries can be grouped under a single UniqueOwnerId.

  • Value is the string to be written into web.config. The 'name' attribute must match previous "Name" parameter. Example: <add name='UniqueName' type='Namespace.ClassName, 4-part strong name' />

Adding a new entry to the web.config:

SPWebConfigModification modification = new SPWebConfigModification(Name,XPath);
modification.Owner = UniqueOwnerId;
modification.Sequence = 0;
modification.Type = SPWebConfigModificationType.EnsureChildNode;
modification.Value = Value;
webapp.WebConfigModifications.Add(modification);         
webapp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
webapp.Update();

Reading a value from the <AppSettings> section of web.config is still possible in a single line of code:

string MySetting = WebConfigurationManager.AppSettings["MySetting"];

It makes sense to store settings for small, simple, global values which do not change often or at all.

Examples would include server names or URLs, list names, and other similar items which might typically be configured after when the application is deployed and then never changed. Potentially, too, these items might be read often as part of the processing of your application code. These all take advantage of the fact that web.config entries are stored in memory when the application starts up (leading to increased performance for repetitive use) and avoid the drawbacks by not changing often.

SharePoint PropertyBag

Many of the important SharePoint objects support a Properties property:

  • SPContentDatabase

  • SPFarm

  • SPServer

  • SPWebApplication

  • SPWeb

  • SPFolder

  • SPListItem

  • SPFile

This property returns a property bag object, which is a collection of key/value pairs. Each key must be uniquely named, each value is a string, and the key/value pair is stored with the owning object in the proper content database. The string value could be a serialized representation of a more complex object if that is required. There are a few important SharePoint objects which do NOT support a property bag - namely SPSite, SPList and SPUser. For two of these objects a property bag on a child object is available:

  • For SPSite, use SPSite.RootWeb.Properties to make use of the property bag of the root Web of the site collection

  • For SPList, use SPList.RootFolder.Properties to use the property bag of the root folder of the List. It is also important to note that SPDocumentLibrary does not expose a property bag. Instead, the document library should be cast as an SPList and then used as above.

There is one additional consideration when working with an SPWeb object. In addition to the Properties property, , SPWeb also supports an AllProperties property, which is a hashtable. Anything you add to Properties will automatically be added to AllProperties, but the reverse is not true. AllProperties is the recommended location to use when storing properties. It is important to keep in mind that this only applies to an SPWeb.

For storing configuration settings, the property bag is the first truly workable option. It gives you the ability to store arbitrary key/value pairs that are scoped at a very specific level.

Pros/Cons

Benefits

  • Native SharePoint functionality - Nothing needs to be added, configured, or activated, and cannot easily be eliminated.. The property bag is available as soon as the owning object is created and exists for the entire life of that object. This means that your application can interact with the property bag regardless of the type of environment; it only needs to be able to get a reference to the owning object.

  • Scope - The property bag option is very granular because property bags are per-object.

  • Backup/Restore - This should be taken care of already as part of your normal content database disaster recovery operations.

  • Management - Properties are stored and managed with their relevant object. For example, backing up a Web site also backs up its property bag. Deleting a Web site also deletes its property bag, which prevents orphaned configuration settings.

  1. Drawbacks
  • Property bag availability - Certain key objects do not support a property bag, although there are ways to work around this issue for all but SPUser objects. No advanced capabilities - There are no default capabilities or methods to review, approve, version, audit or roll back changes that have been made to the property bag. Changes are made directly to the key/value pair and are live and in production immediately upon committing the change.

  • Difficult to store variations - All settings are essentially independent of all other settings, so it can be difficult to store variations of a single setting, such as per-Locale, per-User, and so on.

Sample Code

In the following sample:

  • obj is an object whose property bag you are modifying.

  • Adding a new value to a property bag can be accomplished in two lines of code:

obj.Properties["MySetting"] = MyValue;obj.Update();

Reading a value from the property bag is equally simple:

string MyValue = obj.Properties["MySetting"];

Storing configuration settings in a property bag scoped at a specific level can be a very powerful option.

Using a property bag to store configuration settings makes the most sense when the setting is directly related to one and only one SharePoint object. For example, imagine that you have a process that archives content from lists in your site a certain number of days after the items are marked "complete". It would not be unusual to want to specify that number of days differently on every list. Storing it as a part of each list makes perfect sense; this setting is totally irrelevant to another list or object. (Remember, though, that SPList does not have a property bag, so you need to use the RootFolder property.)

SharePoint Lists

A key capability of SharePoint is the ability to store and manage arbitrary data. For this reason, SharePoint lists provide many capabilities that are ideal for storing configuration setting values. From a developer's point of view, one strong benefit of this option is that it is likely consistent with other actions being performed in the course of custom development so no new knowledge is needed; reading and writing SPListItem objects are common activities for SharePoint developers.

While storing configuration settings in a SharePoint list does have some drawbacks, it is the most full-featured option and the only one that offers all of the advanced features - versioning, approvals, workflow support, recycle bin, and so on, without requiring significant custom code.

The biggest drawback is that this option requires the creation of a list in which to store values. This, in turn, could require the creation of a Site Collection and/or Site, if the list will not be in an existing Site. However, it is unlikely that this presents a significant obstacle to most SharePoint applications.

Pros/Cons

  1. Benefits
  • User Interface - Standard user interface in the form of the standard SharePoint New, Display and Edit forms.

  • Multiple Values - Provides support for complex, related values. For example, a single setting entry in a list can use multiple columns to store multiple potential values based upon various criteria, including language, locale, user role, URL, access mechanism, client application, and so on.

  • Change Management - Support for change management processes ranging from simple one-step approvals to full workflows.

  • Alert - Users or administrators can be alerted when settings are changed.

  • Versioning - Versioning and the ability to roll back changes to a previous value.

  • Auditing - Auditing of setting values to determine who made changes and when they were made.

  • Ease of Use - Offers simple programmability that does not require a different skill set.

  • Security - Allows security trimming and the ability to set security as granular as a specific setting list item.

  • Backup/Restore - Backup/Restore should be taken care of already as part of your normal content database disaster recovery operations.

  • Recycle Bin functionality - Ability to take advantage of the Recycle Bin functionality that is intrinsic to SharePoint.

  • Scope - Granularity can be achieved by architecting a solution with multiple settings lists at different levels:

    • In Central Administration for items scoped to a server farm or Web application

    • In the root Web site of a site collection for items scoped for the site collection

    • In any site for items scoped to the site itself. This granularity also allows for distributed management of settings by making use of native SharePoint capabilities.

  • Multiserver Support - Provided support for multiserver farms by using native SharePoint capabilities.

  • Customizable Fields - Using native SharePoint capabilities, lookup lists, choice fields, user fields, number fields, and any of the default field types --thes e are all available, plus any custom fields you create.

  • Not related to an object - Not tied directly to a specific SharePoint object - this can be of value if the objectrelated to a particular setting needs to be deleted and recreated. In this situation (specifically as opposed to property bags), the setting will not be deleted when the related object is deleted.

  1. Drawbacks
  • Performance - Potential performance implications if settings are used repeatedly in a high volume environment. These can be mitigated to some degree with caching, but be aware that if every page is using these settings, the impact on performance could be very high.

  • Limitation on the types of values - Lists can only store simple values - strings, numbers, etc. They cannot store objects. Even storing serialized objects significantly limits their usefulness because it means that the standard forms are largely useless.

  • Settings removal - Potential for orphaned settings if a piece of functionality is removed but the corresponding setting SPListItem does not get properly cleaned up.

  • List deletion - Potential serious problems if the settings list is deleted. However, this possibility can be protected against by setting proper security and by using impersonation in your code. Additional precautions could include marking the list as hidden, and then providing a custom link to it for the users andadministrators that need access.

Sample Code

Sample code for reading/writing SPListItems is not being shown here as this is a common operation that SharePoint developers are likely already familiar with. If you are not, the following resource in the SharePoint Foundation 2010 Software Development Kit (SDK) can help you get started: Building Block: Lists and Document Libraries.

Storing settings in a SharePoint list can be used in any SharePoint application, for a wide variety of reasons. It is definitely the most approachable, versatile, and easiest option to implement. If required, with a little bit of work, a system that supports scoped configuration lists at the Site, Site Collection and Central Administration level could easily be built.

Hierarchical Object Store (SPPersistedObject)

The last option is a SharePoint construct known as the hierarchical object store. There is no functional difference between the hierarchical object storage and a property bag that is scoped at the SPFarm level, so deciding which to choose is largely a matter of preference. Like property bags, hierarchical object storage is a native capability of SharePoint that is available as soon as a SharePoint server farm is built and is available for the entire life of that farm. This means that any application can interact with the hierarchical object storage without needing to know anything else about the environment. Using the hierarchical object storage is bit more complicated as it requires the creation of a custom object which inherits from SPPersistedObject. Nonetheless, the hierarchical object storage is a valid tool and can be useful in your applications.

Pros/Cons

Benefits

  • Not related to an object - Not tied directly to a specific SharePoint object - this can be of value if the objectrelated to a particular setting needs to be deleted and recreated. In this situation (as opposed to property bags), the setting will not be deleted when the related object is deleted.

  • Global availability - Available globally across the entire server farm.

  • Backup/Restore - Backup/Restore should be taken care of already as part of your standard configuration database disaster recovery operations.

  • Complex values - Can store more complex types, including the following or collections of any of the following:

    • primitive types such as string, int, and GUID

    • objects inheriting from SPPersistedObjects

    • objects inheriting from SPAutoserializingObjects

Drawbacks

  • Custom code - More work than a property bag scoped at the SPWebApplication or SPFarm level - requires you to create a custom class for your settings values and store that. If all you need are simple key/value pairs, a property bag imposes far less overhead.

  • Settings removal - Potential for orphaned settings if a piece of functionality is removed but the object in the hierarchical object store does not get properly cleaned up.

  • User interface - No user interface available out of the box, it would have to be custom-built.

  • Advanced capabilities - No advanced capabilities - there are no out of the box ways to review, approve, version, audit or rollback changes made to the hierarchical object storage objects. Changes are made directly to the key/value pair and are live and in production immediately upon committing the change.

  • Variations - Difficult to store variations (i.e. per-Locale, per-User, etc) of a single setting. All settings are essentially independent of all other settings.

  • Security context - Interacting with the hierarchical object store may be problematic in hosted scenarios or other situations in which your application pool runs with a different security context than your Central Administration Web application.

Sample Code

The first part of interacting with the hierarchical object store requires the creation of a class which inherits from SPPersistedObject to contain each of your settings. Here is a simple example:

public class MyConfig : SPPersistedObject {  [Persisted]  public string MySetting = default(string);  [Persisted]  public int MyNumberSetting = -1;
//A parameter-less constructor is required for serialization.  public MyConfig ()  {  }
//A parameterized constructor is used to create an instance of the object.  public MyConfig (string Name, SPPersistedObject Parent, Guid Id)  : base(Name, Parent, Id)   {  } }

Note the multiple constructors and the use of the Persisted attribute on each field. Note, too, that we are using fields - not properties. While the latter would have been a better implementation, it is not currently an option - fields are the only available choice.

Now that our object exists, we can use it for read/write operations. In the samples below:

  • ParentObj is an object which inherits from SPPersistedObject and serves as the parent for our object

  • Id is a Guid which uniquely identifies this particular instance

Saving a value:

//Create the object.
MyConfig config = new MyConfig ("MySettings", ParentObj, Id);
// Set a value.config.MySetting = "My Value";
config.MyNumberSetting = 123;
// Now save the object into the hierarchical object storage. config.Update();

Reading a value from the hierarchical object storage is a similar operation:

MyConfig config = (MyConfig)SPFarm.Local.GetObject(Id);
//Individual values are available off of the retrieved object.
string MySetting = config.MySetting;
int MyNumberSetting = config.MyNumberSetting;

The hierarchical object storage can be useful in a few scenarios which may apply to your situation:

  • To store information that your application would need to connect to a configuration List - URL, List name, etc. This allows your application to avoid hard coded settings all together. Ideally, this information would then be cached in memory to avoid further look ups.

  • For global settings that need to be accessible across an entire server farm.

  • For complex settings values.

Storing Sensitive Information

In some applications, you are going to need to store sensitive information - passwords, user names, account details, etc. In this case, it is important that you maintain the security of this information. Any of the options presented in this paper would enable you to encrypt values before they are stored, and decrypt them again for use by the application or to be edited by administrators. One option for this was presented above for List-based scenarios. For other options, you can start by reading .NET Framework Developer's Guide - Cryptographic Services.

Performance

Performance is a concern for any application, and certainly something as mundane as reading settings values should not present significant performance problems. With any of the options presented here, the potential for a significant performance problem is very real if used incorrectly. The best way to avoid these problems is to architect solutions and write code with performance in mind.

At a high level, this means that you must be aware of how your application processes and know when it will be retrieving configuration information. You must also be aware of the cost of retrieving each configuration setting to know where the true bottleneck exists.

In each of these scenarios, judicious use of caching is the answer.

Caching in SharePoint presents some unique challenges that must be taken into account. This is primarily because of the multi-server nature of a typical SharePoint Farm. You must also be aware of the volume of content that you are storing in cache and make sure that this is not presenting the very same performance problems you are trying to prevent.

Performance is always a trade-off. Knowledge of your application and testing are the only ways to legitimately tune everything appropriately.

Recommendations

So what is the right answer? Like so many things in SharePoint, the answer is inevitably it depends, or perhaps the answer is really a combination of these options. Global items should go into the hierarchical object storage or a property bag scoped to the farm or Web application. Items scoped at a lower level should be implemented via a property bag attached to the appropriate item - SPSite, SPWeb, SPList, SPListItem, etc. - or in a SharePoint List. Deciding which option(s) work for your application is a factor of many things, including a degree of personal preference.

Regardless of which option is chosen, a few recommendations can be applied globally:

  • Consider caching frequently-used or expensive-to-retrieve values in memory. Your backend storage is still any one of the options presented here; you just have a mechanism for reducing the performance impact of accessing the values.

  • It is important that you have a standard mechanism for reading from and writing to the persistent store. Typically this is accomplished by means of a utility class with a bunch of static methods to handle retrieving and storing values. Besides the obvious benefits of this approach, it also allows you to easily change the back end storage without impacting any of the rest of your application. If all your application needs to do is make a call to SettingsManager.GetValue() and pass in the name of the setting value it needs, it doesn't matter whether that value is coming from a SharePoint List, an external database or the hierarchical object storage - the utility class insulates your application from those details.

  • Similar to above, have a common place where all settings for your application are managed - especially if you are using multiple storage options. Don't force administrators to know where each setting is stored (hierarchical object storage, list, property bag, etc.) to know where they need to go to in order to manage that setting. Have your application do the heavy lifting and pull all of that functionality together in one place for your application.

  • One final recommendation is to set your standards and stick with them. Few things can make an application seem less professional and less well-thought out than a seemingly arbitrary use of different options for storing configuration settings. Know why you are using each option and make sure that it is consistent with the rest of the options chosen for your environment.

Conclusion

Applications have settings that need to be configured and managed. Well-architected applications likely have many such settings. With all of the options available to SharePoint architects and developers to store and manage these configuration values, it is important to have a well-thought out plan that balances performance and ease of use. Using the correct back end store for this information allows your application to perform better and coexist with other SharePoint applications. Making these settings easy for administrators to maintain makes your application more polished and more manageable.

The options presented in this paper range from web.config entries to custom databases; from SharePoint lists to the hierarchical object storage. Knowing which option to use for which situation (and which ones to avoid) is an important part of architecting a SharePoint solution.

Additional Resources

There are several additional resources presented throughout this article. They are collected here just to make it easier to reference them: