I have a C# project that is reading from a stand-alone configuration file named test.config. This is a separate file from the typical App.config.
I am trying to determine if the test.config file contains the optional property TestProperty from code. I attempted to use TestProperty.ElementInformation.IsPresent but this always results in a value of FLASE even when the section element is actually there.
class Program
{
static void Main(string[] args)
{
string filePath = #"C:\Users\username\Desktop\TestProject\ConfigTestApp\Test.Config";
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap(filePath);
fileMap.ExeConfigFilename = Path.GetFileName(filePath);
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
TestConfigSection section = config.GetSection("TestConfigSection") as TestConfigSection;
bool isPresent = section.TestProperty.ElementInformation.IsPresent; // Why is this always false?
}
}
The test.config file looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name ="TestConfigSection" type ="ConfigTestApp.TestConfigSection, ConfigTestApp"/>
</configSections>
<TestConfigSection>
<TestProperty testvalue="testing 123" />
</TestConfigSection>
</configuration>
The backing classes are:
public class TestConfigSection : ConfigurationSection
{
[ConfigurationProperty("TestProperty", IsRequired = true)]
public TestConfigElement TestProperty
{
get
{
return base["TestProperty"] as TestConfigElement;
}
}
}
public class TestConfigElement : ConfigurationElement
{
[ConfigurationProperty("testvalue", IsKey = true, IsRequired = true)]
public string TestValue
{
get { return base["testvalue"] as string; }
set { base["testvalue"] = value; }
}
}
If I move the section into App.config and use ConfigurationManager.GetSection("TestConfigSection"), IsPresent seems to work fine, but I need this to work from a separate file (test.config).
Is there any way to get TestProperty.ElementInformation working or any other way to determine if the test.config file contains the TestProperty property?
Perhaps this is your problem:
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap(filePath);
fileMap.ExeConfigFilename = Path.GetFileName(filePath);
Shouldn't ExeConfigFilename be the full path to the file like this?
fileMap.ExeConfigFilename = filePath;
If that is not the problem, I recently had to do something like you are doing and here is what I did (using your example data).
string filePath = #"C:\Users\username\Desktop\TestProject\ConfigTestApp\Test.Config";
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap { ExeConfigFilename = filePath };
config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
AppSettingsSection section = (AppSettingsSection) config.GetSection("TestConfigSection");
if ( section != null )
{
string testValue = section .Settings["TestProperty"].Value;
}
In my config file I used this type of format:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<TestConfigSection file="">
<clear />
<add key="TestProperty" value="testing 123" />
</TestConfigSection>
</configuration>
Getting some odd behavior from Configuration class. This code
class Program
{
static void Main(string[] args)
{
var configFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
var configuration = ConfigurationManager.OpenExeConfiguration(configFile);
var value = configuration.AppSettings.Settings["Supercali"];
if (value != null) Console.WriteLine("Yay, it finally worked!");
else Console.WriteLine("Still broken.");
configuration.SaveAs("ReadConfig.config");
}
}
with this config in AppDomain.CurrentDomain.SetupInformation.ConfigurationFile:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<appSettings>
<add key="Supercali" value="Fragalistic"/>
</appSettings>
</configuration>
writes the following to "ReadConfig.config"
<?xml version="1.0" encoding="utf-8"?>
<configuration>
</configuration>
and prints this
Still broken.
Looking at it in debug view, AppDomain.CurrentDomain.SetupInformation.ConfigurationFile has the correct file, but OpenExeConfiguration seems to create a blank config. The appSettings section is empty. I'm pretty sure this is wrong, but maybe I'm missing something?
Try this:
var configFile = Assembly.GetExecutingAssembly().Location;
var configuration = ConfigurationManager.OpenExeConfiguration(configFile);
var value = configuration.AppSettings.Settings["Supercali"];
if (value != null) Console.WriteLine("Yay, it finally worked!");
else Console.WriteLine("Still broken.");
configuration.SaveAs("ReadConfig.config");
The OpenExeConfiguration expects the path to a DLL/EXE, not to the .config file.
I have a problem with update my ConfigFile in VS2013 with C#.
I have this code:
Configuration configManager = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
KeyValueConfigurationCollection confCollection = configManager.AppSettings.Settings;
confCollection["ID_Uzivatele"].Value = ID_Uzivatele;
configManager.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(configManager.AppSettings.SectionInformation.Name);
(ID_Uzivatele is a String variable)
and configFile
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="ID_Uzivatele" value="default"/>
</appSettings>
</configuration>
My problem is that(error list):
An unhandled exception of type 'System.NullReferenceException' occurred in KomunikacniAplikace.exe
Anybody has an idea what I am doing wrong?
I would suggest looking at an error case where the setting isn't set: this works for me:
(assuming theres a const for the string so you don't get a typo...)
const string ID_UZIVATELE = "ID_Uzivatele";
Main code:
Configuration configManager = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
KeyValueConfigurationCollection confCollection = configManager.AppSettings.Settings;
if (confCollection.AllKeys.Contains(ID_UZIVATELE)) {
Console.Out.WriteLine("Contains key, modifying : was " + confCollection["ID_Uzivatele"].Value);
confCollection["ID_Uzivatele"].Value = "foo";
} else {
Console.Out.WriteLine("Doesn't contain key, adding");
confCollection.Add(ID_UZIVATELE, "Boom");
}
configManager.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(configManager.AppSettings.SectionInformation.Name);
If the config file is missing, this will generate it( you might want to check that your App.Config is actually being copied to the output folder (which might be the root cause of your error), but building protection against bad config is always helpful.
I have the following in my App.config file
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="save" value="C:\Test"/>
</appSettings>
</configuration>
And the following in my Main.cs
private void tsSaveImage_Click(object sender, EventArgs e)
{
SaveFileDialog sd = new SaveFileDialog();
sd.Filter = "TIFF Files (*.tif)|*.tif";
sd.FilterIndex = 1;
sd.InitialDirectory =
}
I would like to know how I can use the value from the key to set the InitialDirectory. The idea being that Once the app is installed I want users to navigate to app.config file and change this just the once.
Is this a good way or are there better methods?
You can set the initail directory from web.config key by
sd .InitialDirectory = ConfigurationManager.AppSettings[key].ToString();
You need to use the ConfigurationManager:
string value = ConfigurationManager.AppSettings[key];
In your case:
value = ConfigurationManager.AppSettings["save"];
I'm working with C#, Framework 3.5 (VS 2008).
I'm using the ConfigurationManager to load a config (not the default app.config file) into a Configuration object.
Using the Configuration class, I was able to get a ConfigurationSection, but I could not find a way to get the values of that section.
In the config, the ConfigurationSection is of type System.Configuration.NameValueSectionHandler.
For what it worth, when I used the method GetSection of the ConfigurationManager (works only when it was on my default app.config file), I received an object type, that I could cast into collection of pairs of key-value, and I just received the value like a Dictionary. I could not do such cast when I received ConfigurationSection class from the Configuration class however.
EDIT:
Example of the config file:
<configuration>
<configSections>
<section name="MyParams"
type="System.Configuration.NameValueSectionHandler" />
</configSections>
<MyParams>
<add key="FirstParam" value="One"/>
<add key="SecondParam" value="Two"/>
</MyParams>
</configuration>
Example of the way i was able to use it when it was on app.config (the "GetSection" method is for the default app.config only):
NameValueCollection myParamsCollection =
(NameValueCollection)ConfigurationManager.GetSection("MyParams");
Console.WriteLine(myParamsCollection["FirstParam"]);
Console.WriteLine(myParamsCollection["SecondParam"]);
Suffered from exact issue. Problem was because of NameValueSectionHandler in .config file. You should use AppSettingsSection instead:
<configuration>
<configSections>
<section name="DEV" type="System.Configuration.AppSettingsSection" />
<section name="TEST" type="System.Configuration.AppSettingsSection" />
</configSections>
<TEST>
<add key="key" value="value1" />
</TEST>
<DEV>
<add key="key" value="value2" />
</DEV>
</configuration>
then in C# code:
AppSettingsSection section = (AppSettingsSection)ConfigurationManager.GetSection("TEST");
btw NameValueSectionHandler is not supported any more in 2.0.
Here's a good post that shows how to do it.
If you want to read the values from a file other than the app.config, you need to load it into the ConfigurationManager.
Try this method: ConfigurationManager.OpenMappedExeConfiguration()
There's an example of how to use it in the MSDN article.
Try using an AppSettingsSection instead of a NameValueCollection. Something like this:
var section = (AppSettingsSection)config.GetSection(sectionName);
string results = section.Settings[key].Value;
Source:
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/d5079420-40cb-4255-9b3b-f9a41a1f7ad2/
The only way I can get this to work is to manually instantiate the section handler type, pass the raw XML to it, and cast the resulting object.
Seems pretty inefficient, but there you go.
I wrote an extension method to encapsulate this:
public static class ConfigurationSectionExtensions
{
public static T GetAs<T>(this ConfigurationSection section)
{
var sectionInformation = section.SectionInformation;
var sectionHandlerType = Type.GetType(sectionInformation.Type);
if (sectionHandlerType == null)
{
throw new InvalidOperationException(string.Format("Unable to find section handler type '{0}'.", sectionInformation.Type));
}
IConfigurationSectionHandler sectionHandler;
try
{
sectionHandler = (IConfigurationSectionHandler)Activator.CreateInstance(sectionHandlerType);
}
catch (InvalidCastException ex)
{
throw new InvalidOperationException(string.Format("Section handler type '{0}' does not implement IConfigurationSectionHandler.", sectionInformation.Type), ex);
}
var rawXml = sectionInformation.GetRawXml();
if (rawXml == null)
{
return default(T);
}
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(rawXml);
return (T)sectionHandler.Create(null, null, xmlDocument.DocumentElement);
}
}
The way you would call it in your example is:
var map = new ExeConfigurationFileMap
{
ExeConfigFilename = #"c:\\foo.config"
};
var configuration = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
var myParamsSection = configuration.GetSection("MyParams");
var myParamsCollection = myParamsSection.GetAs<NameValueCollection>();
This is an old question, but I use the following class to do the job. It's based on Scott Dorman's blog:
public class NameValueCollectionConfigurationSection : ConfigurationSection
{
private const string COLLECTION_PROP_NAME = "";
public IEnumerable<KeyValuePair<string, string>> GetNameValueItems()
{
foreach ( string key in this.ConfigurationCollection.AllKeys )
{
NameValueConfigurationElement confElement = this.ConfigurationCollection[key];
yield return new KeyValuePair<string, string>
(confElement.Name, confElement.Value);
}
}
[ConfigurationProperty(COLLECTION_PROP_NAME, IsDefaultCollection = true)]
protected NameValueConfigurationCollection ConfCollection
{
get
{
return (NameValueConfigurationCollection) base[COLLECTION_PROP_NAME];
}
}
The usage is straightforward:
Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
NameValueCollectionConfigurationSection config =
(NameValueCollectionConfigurationSection) configuration.GetSection("MyParams");
NameValueCollection myParamsCollection = new NameValueCollection();
config.GetNameValueItems().ToList().ForEach(kvp => myParamsCollection.Add(kvp));
Here are some examples from this blog mentioned earlier:
<configuration>
<Database>
<add key="ConnectionString" value="data source=.;initial catalog=NorthWind;integrated security=SSPI"/>
</Database>
</configuration>
get values:
NameValueCollection db = (NameValueCollection)ConfigurationSettings.GetConfig("Database");
labelConnection2.Text = db["ConnectionString"];
-
Another example:
<Locations
ImportDirectory="C:\Import\Inbox"
ProcessedDirectory ="C:\Import\Processed"
RejectedDirectory ="C:\Import\Rejected"
/>
get value:
Hashtable loc = (Hashtable)ConfigurationSettings.GetConfig("Locations");
labelImport2.Text = loc["ImportDirectory"].ToString();
labelProcessed2.Text = loc["ProcessedDirectory"].ToString();
Try this;
Credit: https://www.limilabs.com/blog/read-system-net-mailsettings-smtp-settings-web-config
SmtpSection section = (SmtpSection)ConfigurationManager.GetSection("system.net/mailSettings/smtp");
string from = section.From;
string host = section.Network.Host;
int port = section.Network.Port;
bool enableSsl = section.Network.EnableSsl;
string user = section.Network.UserName;
string password = section.Network.Password;
This works like a charm
dynamic configSection = ConfigurationManager.GetSection("MyParams");
var theValue = configSection["FirstParam"];