Update Dynamic Web reference URLs During Installation in Visual Studio 2005

I am using dynamic URLBehavior for some web services and during Setup changing web services URLs to appropriate value according to approach described in  article “Walkthrough: Redirecting an Application to Target a Different XML Web Service During Installation “. 
As I already posted, Visual Studio 2005 changed the way where URLs are stored and now saves it inside section of config file. The differences between different types of projects are detailed described in post “How to share dynamic URLs across multiple Web Application Projects” .

I’ve created a class ConfigurationHelper, that helps to update the Dynamic URLs for Web Services.
I’ve tried to utilize ApplicationSettingsBase Class with SettingsProvider derived class to be called from Installer, but didn’t succesded.
It wasn’t too hard to implement it using  System.Configuration.Configuration/ClientSettingsSection and related classes.
One not obvious trick: when you assign value to the existing section element , it is required manually sectSettings.SectionInformation.ForceSave = true.

 Example of use the class:


String VDir = Context.Parameters[“VDir”]; //’TARGETVDIR
String Port = Context.Parameters[“Port”]; //’TARGETPORT
String Site = Context.Parameters[“TARGETSITE”]; //http://jrbii.spaces.live.com/blog/cns!5E74A5E75ECFD62E!183.entry
System.Configuration.Configuration config = ConfigurationHelper.OpenWebConfiguration(Site, VDir);
ConfigurationHelper.WriteDynamicUrl(config, “FSBusinessLib.My.MySettings”, “FSBusinessLib_CommonWS_CommonServices”, ServerName, VirtualDirectory, “CommonServices.asmx”);

//The class code is below:

namespace FSCSharpLib


    using Microsoft.VisualBasic;

    using Microsoft.VisualBasic.CompilerServices;

    using System;

    using System.Collections;

    using System.Diagnostics;

    using System.IO;

    using System.Reflection;

    using System.Windows.Forms;

    using System.Xml;

    using System.Web.Configuration;

    using System.Configuration;

    using FSHelperLib;

    //TODO Use Configuration/ConfigurationManager where appropriate

    //TODO merge with  AppSettingsHelper.cs

    public static class ConfigurationHelper


        public static System.Configuration.Configuration OpenWebConfiguration(string VDir,string Site )



        //’For example, if the IIS metabase path is W3SVC/1/Root/TraceDemo, then the path is “1/TraceDemo”??


            string SiteNumber = Site.Remove(0, Site.LastIndexOf(“/”) + 1);//retrieve “1” from @”/LM/W3SVC/1″;

            string RootVDir = “/” + VDir;//'”/vKnowledge”   

            Trace.WriteLine(“RootVDir “ + RootVDir + ” SiteNumber “ + SiteNumber);

            System.Configuration.Configuration configuration1 = WebConfigurationManager.OpenWebConfiguration(RootVDir, SiteNumber);

            return configuration1;



        /// from http://weblogs.asp.net/bradleyb/archive/2006/05/04/445133.aspx  not applicable for VS03 and in VS05 Web Site projects

        ///“applicationSettings” in VS05 WinForm projects and ClassLibrary projects



e.g “applicationSettings/FSBusinessLib.My.MySettings” or just “FSBusinessLib.My.MySettings”

        ///for CS FSBsnsCsLib.Properties.Settings http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=57690&SiteID=1

        ///for vb FSBusinessLib.My.MySettings



        public static System.Configuration.ClientSettingsSection FindOrCreateSettingsSection(Configuration config, string SectionName)


            const string cnstApplicationSection = “applicationSettings”;

            string sSectionName = StringHelper.RightAfterLast(SectionName, “/”);//remove “applicationSettings/” prefix if applicable ,



            //    sSectionName = cnstApplicationSection + ‘/’ + SectionName;


            ConfigurationSectionGroup grpApplicationSection = config.SectionGroups[cnstApplicationSection];

            if (grpApplicationSection == null)


                grpApplicationSection = new ApplicationSettingsGroup();

                config.SectionGroups.Add(cnstApplicationSection, grpApplicationSection);


            System.Configuration.ClientSettingsSection sectSettings = (ClientSettingsSection)grpApplicationSection.Sections[sSectionName];

            if (sectSettings == null)


                sectSettings = new ClientSettingsSection();

                grpApplicationSection.Sections.Add(sSectionName, sectSettings);

                sectSettings.SectionInformation.ForceSave = true;


                Debug.WriteLine(“Section name: {0} created”,     sectSettings.SectionInformation.Name);




        public static System.Configuration.ClientSettingsSection WriteSettingsValue(ClientSettingsSection sectSettings, string Key,string value)


            SettingElement elem = sectSettings.Settings.Get(Key);

            if (elem == null)


                elem = new SettingElement(Key,SettingsSerializeAs.String );

                XmlDocument doc= new XmlDocument();

                XmlElement xmlValue = doc.CreateElement(“value”);

                xmlValue.InnerText = value;

                SettingValueElement valueElem= new SettingValueElement();

                valueElem.ValueXml = xmlValue;

                elem.Value = valueElem;





                elem.Value.ValueXml.InnerText = value;

                sectSettings.SectionInformation.ForceSave = true; //important, changing Value.ValueXml value is not enough




        //don’t forget to call config.Save after finish all writes

        public static void WriteDynamicUrl(Configuration config,

          string SettingsGroupName, string SettingName, string ServerName,string VirtualPath,string ServiceFile)


            System.Configuration.ClientSettingsSection sectSettings  = ConfigurationHelper.FindOrCreateSettingsSection(config, SettingsGroupName);

            String sValue = HttpRequestHelper.HttpURL(ServerName, VirtualPath, ServiceFile);

            ConfigurationHelper.WriteSettingsValue(sectSettings, SettingName, sValue);



    }//end of class

}//end of namespace