Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to edit an external web.config file?

I am trying to write a winform application that would be able to edit the web.config file of an installed web application. I have read through the ConfigurationManager and WebConfigurationManager class methods but I am unsure as to how I can open the configuration file of a web app and edit it.

I am looking for a method that does not require me to load the config file as a regular XmlDocument, although I am willing to do that if that is the only option available.

Any advice would be appreciated.

like image 453
Krishnamurthy Avatar asked Aug 19 '09 14:08

Krishnamurthy


People also ask

How do I use different web config files?

config (or any file) when you press F5 in Visual Studio. You can have different transformations based on the build configuration. This will enable you to easily have different app settings, connection strings, etc for Debug versus Release. If you want to transform other files you can do that too.


2 Answers

Ok so here is the answer, I have the EXACT same scenario. I wanted to write a winforms app to allow normal users to update the web.config. You have to go about getting the config a goofy way...

// the key of the setting
string key = "MyKey";

// the new value you want to change the setting to
string value = "This is my New Value!";

// the path to the web.config
string path = @"C:\web.config";

// open your web.config, so far this is the ONLY way i've found to do this without it wanting a virtual directory or some nonsense
// even "OpenExeConfiguration" will not work
var config = ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap() { ExeConfigFilename = path }, ConfigurationUserLevel.None);

// now that we have our config, grab the element out of the settings
var element = config.AppSettings.Settings[key];

// it may be null if its not there already
if (element == null)
{
 // we'll handle it not being there by adding it with the new value
 config.AppSettings.Settings.Add(key, value);
}
else
{
 // note: if you wanted to you could inspect the current value via element.Value

 // in this case, its already present, just update the value
 element.Value = value;
}

// save the config, minimal is key here if you dont want huge web.config bloat
config.Save(ConfigurationSaveMode.Minimal, true);

Here is an example of what it does

Before:

<?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="MyKey" value="OldValue" />
  </appSettings>
  <connectionStrings>
    <add name="myConnString" connectionString="blah blah blah" providerName="System.Data.SqlClient" />
  </connectionStrings>
</configuration>

After:

<?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="MyKey" value="This is my New Value!" />
  </appSettings>
  <connectionStrings>
    <add name="myConnString" connectionString="blah blah blah" providerName="System.Data.SqlClient" />
  </connectionStrings>
  <system.web>
    <trust level="Full" />
    <webControls clientScriptsLocation="/aspnet_client/{0}/{1}/" />
  </system.web>
</configuration>

Just be careful, if you give it an invalid path, it will just create a config file at that path / filename. Basically, do a File.Exists check on it first

BTW, while you're at it, you could write a class that represents your settings in your web.config. Once you do this, write your getters/setters to read/write the settings in the web.config. Once THIS is done, you can add this class as a datasource and drag the databound controls onto your winform. This will give you a completely databound winform web.config editor that you can easily hammer out in a matter of minutes. I've got an example at work that I'll post tomorrow.

Fully featured winforms solution

So this is a relatively simple solution to writing a Gui to edit a web.config, some may say its overly complicated when notepad will do just fine but it works for me and my audience.

It basically works as described above, I wrote a class that had the configuration points that I wanted as properties. The ctor opens the file from a path and the getters / setters pull the data out of the returned configuration object, finally it has a save method that writes it out. With this class, I'm able to add the class as a datasource and drag / drop bound controls onto winforms. From there all you have to do is to wire up a button that calls the save method on your class.

Configuration class

using System.Configuration;

// This is a representation of our web.config, we can change the properties and call save to save them
public class WebConfigSettings
{
 // This holds our configuration element so we dont have to reopen the file constantly
 private Configuration config;

 // given a path to a web.config, this ctor will init the class and open the config file so it can map the getters / setters to the values in the config
 public WebConfigSettings(string path)
 {
  // open the config via a method that we wrote, since we'll be opening it in more than 1 location
  this.config = this.OpenConfig(path);
 }

 // Read/Write property that maps to a web.config setting
 public string MySetting
 {
  get { return this.Get("MySetting"); }
  set { this.Set("MySetting", value); }
 }

 // Read/Write property that maps to a web.config setting
 public string MySetting2
 {
  get { return this.Get("MySetting2"); }
  set { this.Set("MySetting2", value); }
 }

 // helper method to get the value of a given key
 private string Get(string key)
 { 
  var element = config.AppSettings.Settings[key];

  // it may be null if its not there already
  if (element == null)
  {
   // we'll handle it not being there by adding it with the new value
   config.AppSettings.Settings.Add(key, "");

   // pull the element again so we can set it below
   element = config.AppSettings.Settings[key];
  }
  return element.Value;
 }

 // helper method to set the value of a given key
 private void Set(string key, string value)
 {
  // now that we have our config, grab the element out of the settings
  var element = this.config.AppSettings.Settings[key];

  // it may be null if its not there already
  if (element == null)
  {
   // we'll handle it not being there by adding it with the new value
   config.AppSettings.Settings.Add(key, value);
  }
  else
  {
   // in this case, its already present, just update the value
   element.Value = value;
  }
 }

 // Writes all the values to the config file
 public void Save()
 {
  // save the config, minimal is key here if you dont want huge web.config bloat
  this.config.Save(ConfigurationSaveMode.Minimal, true);
 }

 public void SaveAs(string newPath)
 {
  this.config.SaveAs(path, ConfigurationSaveMode.Minimal, true);

  // due to some weird .net issue, you have to null the config out after you SaveAs it because next time you try to save, it will error
  this.config = null;
  this.config = this.OpenConfig(newPath);
 }

 // where the magic happens, we'll open the config here     
 protected Configuration OpenConfig(string path)
 {
  return ConfigurationManager.OpenMappedExeConfiguration(
        new ExeConfigurationFileMap() {  ExeConfigFilename = path }, 
        ConfigurationUserLevel.None);   
 }
}

Build and then from there you can just goto your winform designer, goto Data > Show Data Sources (Shift+Alt+D). Right click > Add New Data Source and add it as an object as shown

Data Source Configuration Wizard 1 of 2 http://img109.imageshack.us/img109/8268/98868932.png

Data Source Configuration Wizard 2 of 2 http://img714.imageshack.us/img714/7287/91962513.png

Drag it (WebConfigSettings, the topmost) onto the winform. In my case, I will remove the navigator as that is for a List and I just have one.

Freshly added databound controls http://img96.imageshack.us/img96/8268/29648681.png

You should have something like webConfigSettingsBindingSource at the bottom of the designer (shown in the next pic). Goto the code view and change the ctor to this

public Form1()
{
    InitializeComponent();

    // wire up the actual source of data
    this.webConfigSettingsBindingSource.DataSource = new WebConfigSettings(@"c:\web.config");
}

Add a save button to your winform

Save button added http://img402.imageshack.us/img402/8634/73975062.png

Add the following event handler

private void saveButton_Click(object sender, EventArgs e)
{
    // get our WebConfigSettings object out of the datasource to do some save'n
    var settings = (WebConfigSettings)this.webConfigSettingsBindingSource.DataSource;

    // call save, this will write the changes to the file via the ConfigurationManager
    settings.Save();
}

There, now you have a nice simple databound web.config editor. To add / remove fields, you just modify your WebConfigSettings class, refresh the datasource in the Data Sources window (after a build), and then drag n drop the new fields onto the UI.

You'll still have to wire up some code that specifies a web.config to open, for this example I just hard coded the path.

The cool thing here is all the value that a GUI adds. You can easily add directory or filebrowser dialogs, you can have connection string testers etc. All are very easy to add and very powerful to the end user.

like image 71
Allen Rice Avatar answered Sep 20 '22 16:09

Allen Rice


I highly recommend you to use XElement along with LINQ enabled (LINQ to XML).

For instance you want to change the connectionString. This type of code is good enough

var connString = from c in webConfigXElement.appSettings.connectionString
                        where c.name == "myConnection"
                        select c;

and now you have full control over the <connectionString /> element, and do whatever you want to do with it.

I am referring you to MSDN for learning and also a Kick Start for instant working.

Hope this helps you to have full control over your .xml without pain.

like image 39
Abdul Munim Avatar answered Sep 21 '22 16:09

Abdul Munim