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!
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);
Related
So I have an App.config file setup something like this:
<configuration>
<appSettings>
<add key="Description" value="My too long of a\n description that needs\n new lines so the entire\n thing can be seen."/>
</appSettings>
</configuration>
Now, at run-time, I need to change the Text property of a Label to one of these many descriptions located in the App.config file. If I include the new line character in the App.config, the Label seems to ignore that it is a new line character and instead prints it out literally. However, if I were to remove these new line characters and insert them at run-time, then the Label will recognize them and insert new lines as it should.
My question is, why? Why does the Label ignore them and print them out literally if they come from the App.config?
To use this description from the App.config, this is all I'm doing:
myLabel.Text = ConfigurationManager.AppSettings["Description"];
I would expect \r\n (return, newline) on a Windows system, not just newline. In any case, App.config is XML, so you want the XML escape sequences:
If you want to keep "\n" in xml (for clarity?), then an easy fix:
myLabel.Text = ConfigurationManager.AppSettings["Description"].Replace("\\n","\xa\xd");
I am using .NET 4.0 and I would like to use the app.config file to store same parameter settings. I do the following. I use the Settings tab in the project properties to create my parameters.
This add the information in the app.config file like this:
<MyApp.Properties.Settings>
<setting name="param1" serializeAs="String">
<value>True</value>
</setting>
<MyApp.Properties.Settings>
In my view model (in my code) I can access to the information in this way:
bool myBool = MyApp.Properties.Default.param1;
When I try to change the value in the config file, I try this:
Properties.Settings.Default.param1 = false;
But this causes an error, that param1 is read-only.
So how can I update my config file from my code?
Here's my function to update or add an entry into the app.config for "applicationSettings" section. There might be a better way, but this works for me. If anyone can suggest a better method please share it, we'll always looking for something better.
static string APPNODE = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name + ".Properties.Settings";
static DateTime now = DateTime.Now;
Utilities.UpdateConfig(APPNODE, "lastQueryTime", now.ToString());
static public void UpdateConfig(string section, string key, string value)
{
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
ClientSettingsSection applicationSettingsSection = (ClientSettingsSection)config.SectionGroups["applicationSettings"].Sections[section];
SettingElement element = applicationSettingsSection.Settings.Get(key);
if (null != element)
{
applicationSettingsSection.Settings.Remove(element);
element.Value.ValueXml.InnerXml = value;
applicationSettingsSection.Settings.Add(element);
}
else
{
element = new SettingElement(key, SettingsSerializeAs.String);
element.Value = new SettingValueElement();
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
element.Value.ValueXml = doc.CreateElement("value");
element.Value.ValueXml.InnerXml = value;
applicationSettingsSection.Settings.Add(element);
}
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("applicationSettings");
}
Well, I read the link of Hari Gillala, in which one user suggested to edit directly the app.config file, that is a xml file.
So in project properties-->settings I create the parameters that I need. Then, to load a parameter in code I do the following:
_myViewModelProperty = MyApp.Properties.Settings.Default.MyParam1;
In this way, I can read easily the information of the config parameter. Is typed, so in disign time I can see if the asign is correct or not.
To update de config file, I edit the app.config file with the xml libraries of .NET.
System.Xml.XmlDocument xml = new System.Xml.XmlDocument();
xml.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
System.Xml.XmlNode node;
node = xml.SelectSingleNode("configuration/applicationSettings/MyApp.Properties.Settings/setting[#name='myparam1']");
node.ChildNodes[0].InnerText = myNewValue;
xml.Save(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
In this way, I create a xml document (xml variable) and load the information of the app.config file. Then, I search for the node that I want to update, update its information (InnerText property) and finally I save the changes.
In this way, I can update the app.config. It is what I want, because in a portable application, only one user will use it, and I want that the configuration is applied in any computer in which I run the application.
You should use Properties.Settings to perform this action.
You can look at this documentation for more information.
//modify
Properties.Settings.Default.param1 = false;
//save the setting
Properties.Settings.Default.Save();
Note that if your settings have the Scope of User, which they must be to be writeable, then the properties are saved somewhere else and not in your local config file. See here for the details.
EDIT after discussion in comment and further searches:
My suggestion to achieve the desired result would be to switch to AppSettings.
That is because, after some searches, i found out that appsettings changes the .config file in the Application Data folder (running some tests on my machine confirm that).
Look at comment in the answer to this question .
I am not sure if there is some work around, but if you want your application to have a portable app.config file, i think the only way is to switch to AppSettings which i'm sure can save changes in the app.config found in the program folder.
EDIT 2: Possible solution
I found out a possible solution to make your app portable!
You can change the Provider used by Settings to save the application's settings creating a custom Provider.
The answer to this question provide a link to a code to make applicationsettings portable. I think you give it a try
Mark your setting as usersetting.
Detailed article: http://www.codeproject.com/Articles/25829/User-Settings-Applied
I have this xml file
<?xml version="1.0" encoding="utf-8" ?>
<parameters>
<parameters
registerLink="linkValue"
TextBox.name="nameValue"
/>
</parameters>
I want to print off "LinkValue" and "nameValue" by code:
Console.WriteLine("registerLink: " + registerLink);
Console.WriteLine("TextBox.name: " + TextBox.name);
Thanks
The easiest API is XLinq (System.Xml.Linq)
var doc = XDocument.Load(fileName);
// This should be parameters/parameter, i follow the question with parameters/parameters
var par = doc.Element("parameters").Element("parameters");
registerLink = par.Attribute("registerLink").Value; // string
Your could use an xml reader like this one
http://msdn.microsoft.com/en-us/library/cc189056%28v=vs.95%29.aspx
Once you have a working sample look here to find out how to open an xml reader from a file stream. File must be located in project directory
http://support.microsoft.com/kb/307548
Once you have that done you can add an open file dialog box to find any file on the computer and even validate the .xml extension and more.
Edit: As you can see in the comments below, Hanks solution is better, faster, and easier. My solution would only be useful if you have huge xml files with tons of data. You may still be interested in the file dialog box as well.
I have some complex data which is used for application configuration in xml format. I want to keep this xml string in web.config. Is it possible to add a big xml string in web.config and get it in code everywhere?
If you don't want to write a configuration section handler, you could just put your XML in a custom configuration section that is mapped to IgnoreSectionHandler:
<configuration>
<configSections>
<section
name="myCustomElement"
type="System.Configuration.IgnoreSectionHandler"
allowLocation="false" />
</configSections>
...
<myCustomElement>
... complex XML ...
</myCustomElement>
...
</configuration>
You can then read it using any XML API, e.g. XmlDocument, XDocument, XmlReader classes. E.g.:
XmlDocument doc = new XmlDocument();
doc.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
XmlElement node = doc.SelectSingleNode("/configuration/myCustomElement") as XmlElement;
... etc ...
There are several ways of achieving what you want (an XML fragment that is globally and statically accessible to your application code):
The web.config is already an XML file. You can write a custom configuration section (as described here) in order to fetch the data from your custom XML.
You can encode the XML data (all < to <, > to >, & to &, " to "e;)
You can put the XML data in a <![CDATA[]]> section
Don't use web.config for this, but a Settings file as #Yuck commented
That last option is the best one, in terms of ease of development and usage.
The configuration sections in web.config support long strings, but the string has to be a single line of text so they can fit into an attribute:
<add name="" value="... some very long text can go in here..." />
The string also can't contain quotes or line breaks or other XML markup characters. The data is basically XML and it has to be appropriately encoded.
For example, if you have XML like this:
<root>
<value>10</value>
</root>
it would have to be stored in a configuration value like this:
<add key="Value" value="<root>
<value>10</value>
</root>" />
Which kind of defeats the purpose of a configuration element.
You might be better off storing the configuration value in a separate file on the file system and read it from there into a string or XmlDocument etc.
Okay, so this is sort of a hack...but it may have to be. I'm writing an app in XNA, which from my research into this problem apparently doesn't support XML version 1.1. I'm reading in the contents of an ePub document, and one of the newer books encodes its content as a version 1.1 XML document. This causes my program to crash, however, the structure is the same as the rest. The only thing that is keeping it from working is the hard-coded "1.0" in the XmlDocument class.
Is it possible that I could read in the file from the stream, see if it contains:
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
and simply replace it with "1.0"? Then I could pull it in as an XmlDocument. I'm not doing any writing to the file, or any complex structural reading, just looking for a few specific nodes, and pulling in the values, so I don't know what the ramifications of this would be.
You can do this in a very dodgy way by reading the entire XML file into memory and having your way with it:
string content = "";
// Read the XML file into content
StreamReader reader = new StreamReader("file.xml");
content = reader.ReadToEnd();
reader.Close();
// Find the character position just after the <?xml token, and just before the ?> token
int openIndex = content.IndexOf("<?xml", StringComparison.OrdinalIgnoreCase) + 5;
int closeIndex = content.IndexOf("?>", openIndex);
// Get the bits between <?xml and ?>
string header = content.Substring(openIndex, closeIndex - openIndex);
// Substitute version string.
header = header.Replace("version=\"1.1\"", "version=\"1.0\"");
// Put Humpty Dumpty back together again.
content = string.Concat(content.Substring(0, openIndex), header, content.Substring(closeIndex));
// Feed content into an XMLReader (or equivalent) here.
It works for the example string you provide, but I haven't tested it on imperfectly-formatted XML documents.