2

I need to make changes to a web.config, so I need to read up until the point where I need to make the change, make the change and then write my update out to the file.

So let's say the file contained:

<add key="Version_PSM" value="2.2.0"/>
<add key="Version_MLF" value="2.0.3"/>

And I needed to update the version pf Version_PSM to "2.1". What's the best way to do this? I've tried opening a FileStream and then creating a StreamReader and a StreamWriter using it, but that doesn't work. As I read lines from the file looking for the key I want to update the Writer stays in position at the beginning of the file, so when I write it doesn't overwrite what I've just read - it writes it to the top of the file. So first I tried something like this:

// Repeat in a loop until I find what I'm looking for...
string readLine = sr.ReadLine();
sw.WriteLine(readline);

which advances the position of the writer, but duplicates what's in the file. I need to position the writer to overwrite the text that I want to update and leave everything else as-is.

So I tried just:

readLine = sr.ReadLine();
sw.WriteLine();

but that just writes blanks to the file.

There's gotta be an easy answer here that I'm just missing!

Ben_G
  • 770
  • 2
  • 8
  • 30
  • 1
    LINQ to XML or another XML read/write library is the right way to go here – BradleyDotNET Aug 30 '17 at 21:33
  • AppSettings? ConfigurationManager? – Hackerman Aug 30 '17 at 21:34
  • If you're updating the web.config at runtime have a look at [this question](https://stackoverflow.com/questions/719928/how-do-you-modify-the-web-config-appsettings-at-runtime). Note that your web app **will** restart when you change the config at runtime. – stuartd Aug 30 '17 at 21:37
  • Nope - not at runtime. This only happens during product installs. – Ben_G Aug 30 '17 at 21:44
  • https://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.appsettings%28v=vs.110%29.aspx – Hackerman Aug 31 '17 at 16:08
  • Thanks @Hackerman. That looks simpler than what I ended up with (see below), but I'm glad I learned how to do it using XPath/LINQ anyway. – Ben_G Aug 31 '17 at 20:50

1 Answers1

2

Since you need to change values during installation, you could use LINQ to XML to solve your problem (using System.Xml.Linq;). Typically a web.config file looks like

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
  <appSettings>
    <add key="Version_PSM" value="2.2.0" />
    <add key="Version_MLF" value="2.0.3" />
  </appSettings>
</configuration>

You are able to access and edit nodes based on their names and attributes. After you changed some values you can save the changes. In the following example we are changing the value of the Version_PSM setting. As you can see dealing with the namespace correctly is a bit trick in this case.

//Specify path
string webConfigFile = @"\web.config";

//Load the document and get the default configuration namespace
XDocument doc = XDocument.Load(webConfigFile);
XNamespace netConfigNamespace = doc.Root.GetDefaultNamespace();

//Get and edit the settings
IEnumerable<XElement> settings = doc.Descendants(netConfigNamespace + "appSettings").Elements();
XElement versionPsmNode = settings.FirstOrDefault(a => a.Attribute("key").Value == "Version_PSM");
versionPsmNode?.Attribute("value").SetValue("New value");

//Save the document with the correct namespace
doc.Root.Name = netConfigNamespace + doc.Root.Name.LocalName;
doc.Save(webConfigFile);
Fruchtzwerg
  • 10,999
  • 12
  • 40
  • 49
  • Thanks @Fruchtzwerg. Now my problem is that I need to add a missing value to the web.config and I can't figure out how to do that. I was expecting something like: doc.Descendants(netConfigNamespace + "appsettings").Elements().add(KeyValuePair), but that doesn't work. How can I add a new value to the web.config? – Ben_G Sep 01 '17 at 16:13
  • You need to add a new `XElement` with the attributes to the `appSettings` node. Try out something like `doc.Root.Element(netConfigNamespace + "appSettings").Add(new XElement(netConfigNamespace + "add", new XAttribute("key", "newKey"), new XAttribute("value", "newValue")));` – Fruchtzwerg Sep 01 '17 at 17:40
  • You're a genius @Fruchtzwerg! Thanks so much - that works perfectly! – Ben_G Sep 01 '17 at 17:44