Saving changes to FileConfigurationSource

Topics: Enterprise Library Core
Jul 31, 2008 at 4:36 PM
I was having a problem with saving changes to the ConfigurationSection that were made programatically.  The configuration file was a remote file living outside the web application that is using it, and there are many custom sections that we allow the user to change values view the web application.

After doing some research and not finding a solution and many failed attempts at coding a solution this is the solution that finally worked.  I wanted to post this to see if there is a better way or if this is a good solution that the enterprise blocks may be updated in a future release to support this feature.


  // Get the configuration source.
  IConfigurationSource source = ConfigurationSourceFactory.Create();



  if (source is FileConfigurationSource) {



    // Get the remote file to save the changes to.
    if (string.IsNullOrEmpty(_remotefile)) {
      _remotefile = GetRemoteFilePath();



    // Save the section.
    string updatedxml = string.Empty;



    // Get the xml writer, so that we can get the updated configuration changes.
    StringBuilder output = new StringBuilder();



    using (XmlWriter writer = XmlWriter.Create(output)) {



      // Get the type information.
      Type sectiontype = section.GetType();



      // Use reflection to call the serialization method.
      BindingFlags flags = (BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance);
      MemberInfo[] members = sectiontype.FindMembers(MemberTypes.Method, flags, Type.FilterNameIgnoreCase, "SerializeToXmlElement");



      if (members.Length > 0) { // Found the method now invoke it.
        object result = ((MethodInfo)members[0]).Invoke(section, new object[] { writer, "Element" });



        if (result != null) { // Make sure there were changes.
          if (((bool)result) == true) {
            // Get the changes.
            updatedxml = output.ToString();
// writer.





    if (!string.IsNullOrEmpty(updatedxml)) {



      // Load the updates to the xml.
      XmlDocument updatedsection = new XmlDocument();
      XmlNode updatedsectionnode = updatedsection.SelectSingleNode("Element");



      // Get the source.
      XmlDocument targetfile = new XmlDocument();

      // Find the node that needs to be updated.
XmlNode targetsectionnode = targetfile.SelectSingleNode("configuration/" + section.SectionInformation.SectionName);



      // Perform the update.
      if (updatedsectionnode != null && targetsectionnode != null) {



        // Update the attributes.
        foreach (XmlAttribute attr in updatedsectionnode.Attributes) {
// Has to be cloned because the original belongs to another document.
          XmlAttribute clonedattr = targetsectionnode.OwnerDocument.ImportNode(attr, false) as XmlAttribute;



        // Update the inner xml.
        targetsectionnode.InnerXml = updatedsectionnode.InnerXml;
        // Save the changes.

What I am doing here is getting the remote file path, and then using reflection to get the xml of the ConfigurationElement (ConfigurationSection).  This is the updated xml where using the SectionInformation.GetRawXml did not contain the changes that were made.  Then updating the node in the configuration file using the XmlDocument objects.  I am removing the attributes from the target node before adding them back with the source, to keep in sync any missing or new attributes with out doing a bunch of checks.  I am also setting the InnerXml to reduce the code I would have to write doing itterations for each node and child that the section may have.

I look forward to the feeback, and my hopes is that the Enterprise Team, can add a feature to the FileConfigurationSource that will allow for saving, from programatic changes.  Either that or the information on how to do that with native stuff so that others like me can accomplish our goals.

Thank You, and Thank you EntLib team for doing a great job.