Brian Ritchie's Blog

My ramblings on .NET & other development topics

News



Twitter

Blog Roll

Connect with me

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.

Comments

DotNetShoutout said:

Thank you for submitting this cool story - Trackback from DotNetShoutout

# October 27, 2010 6:14 PM

ian said:

Thanks for the informative post and for actually replying to your readers’ comments. That’s something I don’t see very many blog owners doing and that makes me frustrated. Keep up the good work and I’ll continue coming back here to learn more....

# November 8, 2010 1:05 AM

Toronto Marketing Company said:

These are great guides to help lean about this. The concept is relatively new to many of us, and anything like this that can help us understand the value is very welcome. When I have read this post then I thought that how to configure this new service via web.config.

# November 24, 2010 7:41 AM

narnia said:

nice, love this blog, how do I subscribe

# December 9, 2010 11:54 AM

Max said:

Hi, the region name will be specified ?

if not, will be created a region for user.

How will delete them ?

thanks

# April 18, 2011 7:38 AM

Brian Ritchie's Blog said:

Today at the Jax Code Camp I gave a presentation on scaling out your .NET applications by leveraging

# August 27, 2011 1:30 PM

Scaling Out .NET Presentation at Jax Code Camp 2011 said:

Pingback from  Scaling Out .NET Presentation at Jax Code Camp 2011

# August 28, 2011 12:20 AM

Scaling Out .NET Presentation at Jax Code Camp 2011 said:

Pingback from  Scaling Out .NET Presentation at Jax Code Camp 2011

# August 28, 2011 1:20 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)