Writing to .config files

867 views Asked by At

I am having an issue somewhat similar to this question: C#: Config file error

BACKGROUND

My situation is this: I am using NLog and I have setup a Database target. My app shows an installation page on first run from which I build a connection string for other purposes but would also like to save that same connection string to the NLog.config file. After much searching it would appear that NLog can be changed programatically, but for whatever reason cannot save the changes back to the .config file. Therefore, my plan was to simply do the following:

WHAT I HAVE TRIED

  1. Change the connectionString attribute to simply be connectionStringName instead. Example: connectionStringName="NLogConnection"

  2. Move the <connectionStrings> element from my Web.config to a separate file: ConnectionStrings.config.

  3. Update web.config accordingly:

<connectionStrings configSource="ConnectionStrings.config" />

  1. Write code as follows:

string filePath = HostingEnvironment.MapPath(Path.Combine(httpRequest.ApplicationPath, "ConnectionStrings.config")); var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = filePath }; var configFile = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); configFile.ConnectionStrings.ConnectionStrings["NLogConnection"].ConnectionString = connectionString; configFile.Save();

OUTCOME

Seemed like a nice plan. However.. the code above throws an error about not having a <configuration> tag and if I add that tag, the site throws an error about the tag being there! No win situation here... does anyone have any ideas on how to solve this one? Ideally it would be nice if there was a way to properly modify external .config files which are only a part of the main web config. I may have to revert to manually reading/writing the raw XML.. but I would prefer not to if there's a better/more elegant way.

SOLUTION

Many thanks to @Julian; I now have a working solution. I added this in my Global.asax:

private static void TryUpdateNLogConnectionString(string connectionString)
        {
            try
            {
                var target = LogManager.Configuration.FindTargetByName("database");

                DatabaseTarget databaseTarget = null;
                var wrapperTarget = target as WrapperTargetBase;

                // Unwrap the target if necessary.
                if (wrapperTarget == null)
                {
                    databaseTarget = target as DatabaseTarget;
                }
                else
                {
                    databaseTarget = wrapperTarget.WrappedTarget as DatabaseTarget;
                }

                databaseTarget.ConnectionString = connectionString;
            }
            catch { }
        }
1

There are 1 answers

0
Julian On BEST ANSWER

You can change settings programmatically in NLog, but you can't serialize those settings to the XML, yet.

What you can do:

  1. Save the setting to the <appSettings> when changed
  2. read the <appSettings> when needed.

eg

using System.Web.Configuration;
using System.Configuration;

Configuration config = WebConfigurationManager.OpenWebConfiguration("/");
config.AppSettings.Settings["NlogConnectionString"].Value = "NewValue";
config.Save(ConfigurationSaveMode.Modified);

Edit the connectionstring when needed in NLog:

DatabaseTarget databaseTarget = LogManager.Configuration.FindTargetByName(targetName) as DatabaseTarget;
databaseTarget.ConnectionString = System.Configuration.ConfigurationManager.AppSettings["NlogConnectionString"];