views:

844

answers:

5

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.

A: 

Hi, all app.config and web.config are jsut xml files you can open and edit them using XMLDocument, XMLWriter .etc.. BEst Regards, Iordan

IordanTanev
The question specifically said that they didn't want to use the generic XMLDocument objects (which is a good idea since you dont need to re-invent the wheel).
Russell
A: 

Any winforms application for editing a web.config would basically be a fancy XML editor. This doesn't have to be just a plaintext editor, of course. You could make basic assumptions about the structure and content of a web.config file so that your winforms editor would have web.config-specific checkboxes/text entry fields/radio buttons/etc.

Matt Ball
+2  A: 

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

Data Source Configuration Wizard 2 of 2

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

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

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.

Allen
I give you a **"Vote Up"**. Although your post jusssst answers the question.
Munim Abdul
what about now :-P
Allen
A: 

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.

Munim Abdul
he specifically said he didn't want to do this. Everyone here knows a web.config is xml and that you can open and edit it any way you see fit.
Allen
@Allen `ConfigurationManager` class does serve the purpose of modifying/adding. You should also keep in mind that `ConfigurationManager` class has control over `AppSettings` and `ConnectionStrings`.`XmlDocument` is pain and `ConfigurationManager` is one of the solution for `.config` files. Believe me `LINQ to XML` is much more convenient when you need the power.By the way Allen, you should know your manners. You should know when to **Vote Up** or **Vote Down**Cheers
Munim Abdul
A: 

Here you go, I wrote a toy app (VB.NET Windows client) that edits XML files using a Tree / Grid for navigating and editing.

You might get some ideas from it. The VS project file for it is here or just an MSI to install it is here, if you want to try it out on your web.config.

It loads the file into a DataSet (DataSet.ReadXML()) which parses it into DataTables, then displays and allows editing of the contents in a standard DataGrid. Then it will save the edited content back to the XML file (DataSet.WriteXML()).

Ron Savage