Configuring AppFabric Session Hosts Dynamically

Windows Server AppFabric has finally brought a performant, fault-taulerant session provider to ASP.NET.  Originally, this technology was part of the Velocity Project.  Very cool stuff.  There are lots of articles out there about how to configure this new service via web.config. Now, I love web.config as much as the next person, but it makes my deployment process painful.  Sure there is the new web.config transformation process, but it requires the code to go back through the build process which makes it hard to move from environment to environment.  To solve these and other problems, we have a custom configuration system to handle environment specific settings. 

And this brings us back to the problem with the AppFabric cache section in the web.config: it specifies the host names...which of course are environment specific.

<dataCacheClient>
  <hosts>
    <host name="cachehost1" cachePort="22233" />
  </hosts>
</dataCacheClient>

Unfortunately, the web.config is the only way to configure the session provider.  Sure, Microsoft provides a programmatic way to configure the cache...just not in terms of the session provider. Luckily, there is a way around this problem: rewrite the configuration file on start up.

First, we'll move the configuration into an external file using the configSource attribute and add the restartOnExternalChanges attribute to the configSections/section element.  This will allow us to change the configuration dynamically without touching the web.config or causing the application to reload when the external file is updated.

<?xml version="1.0"?>
<configuration>
    <configSections>
        <section name="dataCacheClient" type="Microsoft.ApplicationServer.Caching.DataCacheClientSection, 
             Microsoft.ApplicationServer.Caching.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
" allowLocation="true" allowDefinition="Everywhere" restartOnExternalChanges="false" /> </configSections> <dataCacheClient configSource="dataCacheClient.xml"/> <system.web> <sessionState mode="Custom" customProvider="AppFabricCacheSessionStoreProvider" timeout="20" cookieless="UseCookies"> <providers> <!-- specify the named cache for session data --> <add name="AppFabricCacheSessionStoreProvider" type="Microsoft.ApplicationServer.Caching.DataCacheSessionStoreProvider" cacheName="SessionStateCache" sharedId="SharedApp"/> </providers> </sessionState> <compilation debug="true" targetFramework="4.0"> <assemblies> <add assembly="Microsoft.ApplicationServer.Caching.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <add assembly="Microsoft.ApplicationServer.Caching.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> </assemblies> </compilation> </system.web> </configuration>

Second, we'll add code to the App_Code/AppStart.cs file.  This code will automatically run when the application starts up to rewrite the external configuration file with the correct settings.  Since AppStart occurs before the session provider is initialized, the Configuration Manager has not loaded this part of the configuration yet.

using System;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;
public class AppStart
{
    public static void AppInitialize()
    {
        DataCacheClientConfigWriter.RefreshConfig(new string[] {"localhost"}, 22233);
    }
}
public static class DataCacheClientConfigWriter
{
    public static void WriteTo(string path, string[] hosts, int port)
    {
        XDocument doc=new XDocument(
            new XElement("dataCacheClient", 
                new XElement("hosts", (from host in hosts select 
                       new XElement("host", new XAttribute("name", host), 
                       new XAttribute("cachePort", port)))
                )));
        doc.Save(path);
    }
    public static void RefreshConfig(string[] hosts, int port)
    {
        WriteTo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "dataCacheClient.xml"), 
                       hosts, port); } }

And that is it, now our configuration is loaded from the dynamically updated file.  This approach could also be used for other areas of .NET that can only be configured using the web.config.

Here's a sample project with all of the pieces.

2 Comments

Comments have been disabled for this content.