Reloading configuration without restarting application using ConfigurationManager.RefreshSection

StackOverflow https://stackoverflow.com/questions/179254

Question

Has anyone got this working in a web application?

No matter what I do it seems that my appSettings section (redirected from web.config using appSettings file=".\Site\site.config") does not get reloaded.

Am I doomed to the case of having to just restart the application? I was hoping this method would lead me to a more performant solution.

Update:

By 'reloading' I mean refreshing ConfigurationManager.AppSettings without having to completely restart my ASP.NET application and having to incur the usual startup latency.

Was it helpful?

Solution

Make sure you are passing the correct case sensitive value to RefreshSection, i.e.

ConfigurationManager.RefreshSection("appSettings");

OTHER TIPS

This seems to be a flaw (maybe a bug) when using an external config file for your appSettings. I've tried it using the configSource attribute and RefreshSection simply never works, I'm assuming this is the same when using the file attribute. If you move your appSettings back inside your web.config RefreshSection will work perfectly but otherwise I'm afraid you're doomed.

For some reason ConfigurationManager.RefreshSection("appSettings") wasn't working for me. Reloading the Web.Config into a Configuration object seems to work correctly. The following code assumes the Web.Config file is one directory below the executing (bin) folder.

ExeConfigurationFileMap configMap = new ExeConfigurationFileMap();
Uri uriAssemblyFolder = new Uri(System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase));
string appPath = uriAssemblyFolder.LocalPath;
configMap.ExeConfigFilename = appPath + @"\..\" + "Web.config";
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel.None); 

And is used like:

string webConfigVariable = config.AppSettings.Settings["webConfigVariable"].Value;

As an alternative you could write your own ConfigSection and set restartOnExternalChanges="false".

Then, when reading the section with ConfigurationManager.GetSection("yourSection") the settings will be auto-refreshed without an application restart.

And you could implement your settings strongly typed or as NameValueCollection.

.RefreshSection() does not work when the appSettings is external.

You can however use the following to change a value:

ConfigurationManager.AppSettings.Set(key, value)

This will NOT change the setting on file, only the loaded value in memory.

So instead of using RefreshSection I did the following:

string configFile="path to your config file";
XmlDocument xml = new XmlDocument();
xml.Load(configFile);

foreach (XmlNode node in xml.SelectNodes("/appSettings/add"))
{
    string key = node.Attributes["key"].Value;
    string value= node.Attributes["value"].Value;
    ConfigurationManager.AppSettings.Set(key, value);
}

Any subsequent calls to AppSettings.Get will contain the updated value.

The appSettings will then be updated without needing to restart the application.

Yes. you are stuck with iis restarting.

There is a feature with asp.net 4.0 and iis 7.5 where the initial startup is removed.

I am not sure if this is possible in a web app, but it works in a desktop app. Try using ConfigurationSettings rather than ConfigurationManager (it will yell at you for using outdated classes...), then reading all the data into a class. When you wish to refresh, simply create a new instance and drop all references to the old instance. My theory for why this works (might be wrong): when you don't directly access the app.config file the entire time you are running, the file lock is dropped by the application. Then, edits can be made when you are not accessing the file.

The App.Config settings are cached in memory when the application starts. For this reason, I don't think you'll be able to change those settings without restarting your application. One alternative that should be pretty straight forward would be to create a separate, simple XML configuration file, and handle loading/caching/reloading it yourself.

To write, call it this way:

Dim config As System.Configuration.Configuration = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~")

Return AddOrUpdateAppSetting(config, "YourSettingKey", "YourValueForTheKey")

To read and be sure you get the values in file, instead of those in cache, read it this way:

Dim config As System.Configuration.Configuration = WebConfigurationManager.OpenWebConfiguration("~")
  Return config.AppSettings.Settings("TheKeyYouWantTheValue").Value

Full example:

Protected Shared Function AddOrUpdateAppSetting( _
       ByVal Config As System.Configuration.Configuration _
     , ByVal TheKey As String _
     , ByVal TheValue As String _
     ) As Boolean</p>

    Dim retval As Boolean = True

    Dim Itm As System.Configuration.KeyValueConfigurationElement = _
        Config.AppSettings.Settings.Item(TheKey)
    If Itm Is Nothing Then
        If Config.AppSettings.Settings.IsReadOnly Then
        retval = False
        Else
        Config.AppSettings.Settings.Add(TheKey, TheValue)
        End If


    Else
        ' config.AppSettings.Settings(thekey).Value = thevalue
        If Itm.IsReadOnly Then
            retval = False
        Else
            Itm.Value = TheValue
        End If


    End If
    If retval Then
     Try
        Config.Save(ConfigurationSaveMode.Modified)

     Catch ex As Exception
        retval = False
     End Try

    End If

    Return retval

End Function

Have you tried storing your AppSettings in its own external file?

From app.config/web.config:

<appSettings configSource="appSettings.config"></appSettings>

appSettings.config:

<?xml version="1.0"?>
<appSettings>
  <add key="SomeKey" value="SomeValue" />
</appSettings>

Changes made to appSettings.config should be reflected instantly. More info: http://msdn.microsoft.com/en-us/library/system.configuration.sectioninformation.configsource.aspx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top