Pretty much every enterprise application uses configuration settings of some sort, managing these settings across several environments can be a challenging task. Luckily Patterns and Practices SPG 2010 package provides us plenty of guidance when designing applications or customizations that run on top of SharePoint Server 2010 as well as some foundation classes. SPG 2010 from Patterns and Practices is a must read for every SharePoint developer, so if you are not familiar with it head over to codeplex  site right now and add a task in your outlook 2010 to get familiar with it. In this article I will show how to integrate application settings manager into your build process to setup environment specific settings.

ApplicationSettingsHelper

This is a helper class I wrote to wrap all calls to SPG application settings manager, there are couple of reasons behind this

  1. I needed a simple interface to call from PowerShell script
  2. My developers need not necessary have to know how to use the application settings manager
  3. It provides me an option to swap out the Application Settings Manager with some other solution incase we run into performance or other issues with out impacting application code as well as my development team

This helper class has 3 methods

AddSetting(string key, object value) Adds a specific setting to property bag using the application settings manager
GetValue<TValue>(string key) Gets value for setting using the application settings manager
RemoveSetting(string key) Removes a specific setting from property bag using the application settings manager

Another thing I want to point out is since the SPG Application settings manager expects a “SPContext” which is not going to be there when its invoked from PowerShell script, in “AddSetting” method check to see if SPContext exists if yes then SPSite reference is obtained from it otherwise the code instantiates SPSite using the url passed via constructor and use the SetWeb method on ConfigManager class to provide the Application Settings Manager a web context. If you don’t do this you will get exception when there is no SPContext

/// <summary>
/// store a application setting in a list using the P&P application settings manager
/// </summary>
/// <param name="key">config key</param>
/// <param name="value">key value</param>
public void AddSetting(string key, object value)
{
   SPSite site = null;
   Boolean disposeSite = false; 
 
   try
   {
       IConfigManager configManager = GetConfigManager();
       if (configManager == null) return;
       if (SPContext.Current == null && !String.IsNullOrEmpty(this._urlField))
       {
           site = new SPSite(this._urlField);
           disposeSite = true;
       }
       else
       {
           site = SPContext.Current.Site;
       }
       configManager.SetWeb(site.RootWeb);
       IPropertyBag bag = configManager.GetPropertyBag(ConfigLevel.CurrentSPWebApplication);
       if (bag == null) return;
       configManager.SetInPropertyBag(key, value, bag);
   }
   finally
   {
       if (site != null && disposeSite)
       {
           ((IDisposable)site).Dispose();
       }
   }
}

Define all your environment specific application configuration settings in an xml file, create one file for each environment you have in your scenario, here is how the XML file looks like. For the purpose of this article, in the sample xml file I have just one setting called “WS.Url”, but in real world scenarios you will have more than just one.

<Settings>
  <add Name="WS.Url" Value="http://teamsites.contoso.local/sites/team1/_vti_bin/Lists.asmx" />    
</Settings>

Assuming you all are using PowerShell scripting for deploying your WSP’s, script below will read the xml file and for each setting define it will call the “AddSetting” method to set environment specific settings

PowerShell:

function UpdateApplicationSettings()
{
    param($EnvSettingsFile, $WebUrl)
    
    if([String]::IsNullOrEmpty($EnvSettingsFile))
    {
        $EnvSettingsFile = $(Read-Host -Prompt "Enter full path to environment settings file")
    }
    if([string]::IsNullOrEmpty($WebUrl))
    {
        $WebUrl = $(Read-Host -Prompt "Enter URL for web application")
    }
    $EnvSettingsXmlDoc = [xml] (Get-Content $EnvSettingsFile)
    
    $lib = New-Object System.Reflection.AssemblyName("RPG.Common, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=fbb9d9a16b3503f0")
    [System.Reflection.Assembly]::Load($lib)
    
    $helper = New-Object RPG.Common.AppSettingsHelper($WebUrl)
    $EnvSettingsXmlDoc.SelectNodes("/Settings/add")|ForEach-Object{
        $key = $_.Attributes.GetNamedItem("Name").Value    
        $value = $_.Attributes.GetNamedItem("Value").Value
        $helper.AddSetting($key, $value)
    }
}

I wrote a sample WebPart just to show how application could be consuming these environment specific settings set via your deployment PowerShell script

SNAGHTML23017f8

There you have it, a simple approach to integrating updating environment specific application settings into your build process. Download SPG 2010 from CodePlex and start building some cool applications on SharePoint 2010 Smile

Cheers

</Ram>

Technorati Tags: ,