One of the powerful features provided by SharePoint is the encapsulation of functionality into web parts and the ability for users to manage the configuration of those web parts.
And one of the biggest pains for users of SharePoint is the perpetual configuration of web parts.
Ah, the trade-offs of flexibility.
On a recent project, we used an approach that keeps the powerful capability of web part configuration but injects some flexible defaulting logic to (hopefully!) keep the user from removing all of his or her hair.
So how does it work? Suppose you’ve got a web part that renders the words "Sample Web Part" and contains properties to specify the background color and text color (fancy, huh?). So you kick the page into edit mode, drop the web part on the page, and modify its properties. As you might expect, the tool pane for the web part looks something like this:
And the web part renders as you might expect:
And that process is really no big deal — unless you have to add the web part to 90 pages throughout your site. Wouldn’t it be great if the properties could automatically default to a given value so that when the web part is dropped on the page, you don’t have to modify any of the properties?
Doing this isn’t hard from a development standpoint, but where should the default values go? You could certainly go with the default ASP.NET approach and put them in the site’s web.config file, but I propose in the spirit of SharePoint’s model of user empowerment that this data should go in a SharePoint list.
In our case, we used a list in the root web of the site collection that looks like this:
The next step we took was to create single appSettings entry in the web.config to specify the location of the configuration list:
We then created a base class used by our web parts that looks for this appSettings entry and loads the contents of the specified list into an internal hashtable to be used by inherited classes.
To make it work, the web part properties for each inherited class look something like this:
Note that the implementation allows the user to override the default value (represented here in the "_textColor" private member); however, if the user doesn’t explicitly provide a value, the web part calls the protected GetAutoConfigValue method on the base class. That method checks to see if a default value is specified in the site config list:
The GetConfigValues method that’s called here simply loads the values from the auto configuration list (if one is specified) into a hashtable.
So what’s the final outcome? You can drop the web part on a page and it now automatically configures itself based on the values from the site configuration list:
What if you want to change the background of all of those web parts on the site to purple? Fine: simply update the setting in the configuration list. But what if there’s one web part that needs a different text color? No problem: set the properties of that individual web part and they won’t be overridden by changes to the default configuration.
Here are a few more ideas from our implementation:
- We set security on the configuration list in the root web so that only a few select users have permissions. The code in the web part ensures that it can read that list by using the SPSecurity.RunWithElevatedPrivileges method. Thus, even though most of the users don’t have access to that list, they can still be presented with web parts that are configured by it.
- We were worried that depending on the number of web parts and properties on a given page, there might be quite a large load involved with getting information from the configuration list. To mitigate this, we used the caching application block from the Microsoft Enterprise Library to cache the hashtable containing property defaults for a few minutes at a time. Now instead of hitting the SharePoint list multiple times for each page load, the list is hit every few minutes to update the hashtable in the cache. It works pretty well.
I’m sure there are portions of this solution that we can improve on, but I’m happy with the balance that it brings to the "flexibility vs. time-to-configure" tradeoff.
What are some of the ways you’ve designed solutions to make life easier for your users?