How to override settings.settings variable by app.config variable - c#

How can I change (or override) a settings.settings variable by adding a variable to the app.config on production?
Is this possible anyway?

You have to directly reference the applicationSettings you're trying to override and explicitly specify the property that has a replaced value.
<configuration>
<!-- section definitions for all elements in <configuration> tag -->
<configSections>
<!-- section group, meaning: there will be a <applicationSettings> tag in you configuration-->
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<!-- defines that there will be a <appname.Properties.Settings> tag inside your <applicationSettings> tag -->
<section name="appname.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<appname.Properties.Settings>
<!-- name of the property you want to override -->
<setting name="setting1" serializeAs="String">
<!-- new value -->
<value>new string value</value>
</setting>
</appname.Properties.Settings>
</applicationSettings>
</configuration>

It depends on the scope of the settings. If its an application scope setting changing its value in app.config is sufficient.
However, if its a user scope setting then the value present in app.config is just the default used to new users and every user that already used the application will have the currently used value stored in a separate file, the user.config, so changing the value in app.config will have no effect to users that already run the application once.
Due to this changing the value of an user scope setting can be a troublesome task. You can check the following answer for more information on changing a user scope setting:
Changing User Scope Application Setting

Use different config files for production and for you. Basically on production you would compile in RELEASE, so if you use Visual Studio for it, use post build events to copy RELEASE config file in case you prepare a build for production.
I would prefer this instead of changing it from the code, as for someone else is much easier to see the differenc in config file, then going deep into the code to find all the if/else stuff.

For an application scope connection string value:
<connectionStrings>
<add name="appname.Properties.Settings.setting1" connectionString="test string" providerName="dbProvider"/>
</connectionStrings>

Only through code:
e.g.
if (bool.Parse(ConfigurationManager.AppSettings["overridethis"].ToString()))
{
//use overridden value
}
If however, your issue is maintaining different configuration values in different environments, then I would use AppSettings instead.
You can then use a developer override file.
<appSettings file="..\user.config">
See http://www.compiledthoughts.com/2005/03/overriding-webconfig-app-settings-with.html

Related

Problem calling a second .config for keys in C#

I need a second .config to manage alot of keys. I tried using
<configSections>
<section name="apiConnection" type="CustomConfig.apiConnectionSection, CustomConfig" />
</configSections>
<apiConnection configSource ="ApiConnection.config"/>
Where "ApiConnection.config" is my .config file to manage keys but this didn't work.
Then i tried the "file" property in appSettings.
<appSettings file="ApiConnection.config">
This didn't work either. I Tried with:
../ApiConnection.config
~/ApiConnection.config
But nothing...
Some ideas?
The program doesnt break, just not show me the keys when i try with the ConfigurationManager.
https://i.stack.imgur.com/6xHK2.png
<img src= https://i.stack.imgur.com/6xHK2.png/>
EDIT
My file is in root path (with web.config)
The file looks like
<?xml version="1.0" encoding="utf-8"?>
<appSettings>
<add key="Secret" value="z8xyHkN3Eju2TS9u-4MXeI2AbZiuTsF7xYJcjIJ" />
<add key="Audience" value="keyforms"/>
</appSettings>
Ok I think I know what your problem is based on your last comment.
This code is creating a new configuration section called apiConnection.
<configSections>
<section name="apiConnection" type="CustomConfig.apiConnectionSection, CustomConfig" />
</configSections>
<apiConnection configSource ="ApiConnection.config"/>
This section's values will not be contained in app settings. So you won't be able to access it via
ConfigurationManager.AppSettings
You will need to access it in a different manner. Now the exact manner will depend on your implementation of CustomConfig.apiConnectionSection and CustomConfig. I would search your code to find the class that defines how this works.
This example shows how to pull values from a custom config section, SecureAppSettings that uses the NameValueCollection in the same manner as AppSettings. You will have to do some digging to figure out what Types you will need to utilize.
NameValueCollection section = (NameValueCollection)ConfigurationManager.GetSection("secureAppSettings");
string userName = section["userName"];

Extend an element in App.config

We have an app.config we are using with Carbonator:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="carbonator" type="Crypton.Carbonator.Config.CarbonatorSection, Crypton.Carbonator"/>
</configSections>
<carbonator defaultCulture="en-US" logLevel="1" collectionInterval="1000" reportingInterval="1000" >
<statsd server="127.0.0.1" port="8125" />
<counters>
<add path="processor_information.pct_processor_time.total" category="Processor" counter="% Processor Time" instance="_Total" />
<add path="memory.available_MBytes" category="Memory" counter="Available MBytes" instance="" />
<add path="memory.pct_commited_bytes_in_use" category="Memory" counter="% Committed Bytes In Use" instance="" />
</counters>
</carbonator>
</configuration>
We want to allow users to configure their own custom counters in an external config file that we reference from the <counters> element. For example, we would like to allow the user config file to look like:
<add path="logical_disk.pct_free_space.C" category="LogicalDisk" counter="% Free Space" instance="C:" />
<add path="logical_disk.disk_read_bytes_per_sec.C" category="LogicalDisk" counter="Disk Read Bytes/sec" instance="C:" />
<add path="logical_disk.disk_write_bytes_per_sec.C" category="LogicalDisk" counter="Disk Write Bytes/sec" instance="C:" />
I don't even know if this is possible outside of an appConfig element, but any help is appreciated.
According to this answer it should be possible. Same way is also described in this article.
But I don't think it's a good idea for one reason - if a user makes a mistake in his configuration extension, it will prevent the application from executing since the application configuration became invalid.
I would rather use the configuration in the app.config file to provide default values and implement some user configuration myself. Is such case, you can use whatever configuration format you like, for example JSON, which would be also better (easier to create and edit) for users. In your application, you simply merge both configurations (app.config values are default values which will be overwritten by the user's configuration).

Castle Windsor: How to convert an appSettings dependency to a list or an array?

I have a component that depends on a list of strings:
// ctor
public MyComponent(IList<string> someStrings) { ... }
Using Castle Windsor, I'm trying to provide this dependency from the AppSettings section of my app.config file like so:
container.Register(Component
.For<IMyComponent>()
.ImplementedBy<MyComponent>()
.DependsOn(Dependency.OnAppSettingsValue("someStrings", "SomeStrings"))
);
The Windsor documentation on Inline Dependencies says:
appSettings and conversion: Values in the config file are stored as text, yet the dependencies in your code may be of other types (TimeSpan in this example). Windsor has got you covered, and for most cases will perform the appropriate conversion for you.
Does this cover my case where I'd like to convert to IList<string>?
If so, what is the correct way to enter the list of strings in the app.config file?
If not, is there an extensibility point where I can specify my own conversion?
The bigger issue here is that it's not trivial to store a list of values in appSettings. This question addresses it and the best answer is to create your own section in the settings file, which you then have to access via ConfigurationManager.GetSection() instead of ConfigurationManager.AppSettings.Get(), which is what Dependency.OnAppSettingsValue() uses. Looking through the rest of the Dependency class, it seems there's no built-in way to do this.
However, if it really is just strings that you need, you have at least two options that aren't all that bad (in my opinion).
1. Store the strings in your App.config file using a StringCollection.
This is just a shorter, built-in version of creating your own section in App.config. Use the editor in Visual Studio's Project Properties page to add an application setting of type StringCollection. This will make your App.config look something like this:
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="YourApplication.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<YourApplication.Properties.Settings>
<setting name="SomeStrings" serializeAs="Xml">
<value>
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<string>one</string>
<string>two</string>
<string>three</string>
</ArrayOfString>
</value>
</setting>
</YourApplication.Properties.Settings>
</applicationSettings>
</configuration>
Then when configuring your component:
// StringCollection only implements IList, so cast, then convert
var someStrings = Properties.Settings.Default.SomeStrings.Cast<string>().ToArray();
container.Register(Component.For<IMyComponent>()
.ImplementedBy<MyComponent>()
.LifestyleTransient()
.DependsOn(Dependency.OnValue<IList<string>>(someStrings)));
2. Store the strings as a delimited list in appSettings, then manually split them.
This is likely the simpler approach, though assumes you can figure out a delimiter for your strings (which may not always be the case). Add the values to your App.config file:
<configuration>
<appSettings>
<add key="SomeStrings" value="one;two;three;four" />
</appSettings>
</configuration>
Then when configuring your component:
var someStrings = ConfigurationManager.AppSettings["SomeStrings"].Split(';');
container.Register(Component.For<IMyComponent>()
.ImplementedBy<MyComponent>()
.LifestyleTransient()
.DependsOn(Dependency.OnValue<IList<string>>(someStrings)));
In either case, we're just adding a small amount of work on top of Dependency.OnValue, which is all Dependency.OnAppSettingsValue does anyways.
I think this answers your questions, but to be explicit:
Yes, but you're doing the conversion yourself so you can convert to anything you'd like.
See the linked question and accepted answer, or use a StringCollection.
Dependency.OnValue is the extension (in my opinion), and I don't know of or see any other place where you would do it. However, given the steps above I don't think this is necessary.

I want to get different tags of App.config File in C#

I have to get string inside Setting-> Value in C#. How to reach there through code and fetch that value from App.config file. Please help me. Thank you.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="MyApplication.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<applicationSettings>
<MyApplication.Properties.Settings>
**<setting name="ConnectionString" serializeAs="String">
<value>server=127.0.0.1;uid=root;pwd=root;database=MyApplication_db;</
</setting>**
</VASI_Application.Properties.Settings>
</applicationSettings>
</configuration>
You can use the following code:
var section = (ClientSettingsSection)ConfigurationManager.GetSection("applicationSettings/MyApplication.Properties.Settings");
var settingElement = section.Settings.Get("ConnectionString");
var settingValue = settingElement.Value.ValueXml.InnerText;
// settingValue equals "server=127.0.0.1;uid=root;pwd=root;database=MyApplication_db;"
First, you retrieve the ClientSettingsSection section. The name of the section is a combination of the name of the "applicationSettings" section and its inner "MyApplication.Properties.Settings" section. Then, you retrieve the actual settings by calling Settings.Get("ConnectionString") on the returned ClientSettingsSection instance. Finally, you can use the Value.ValueXml.InnerText property of the returned setting to get to the actual value.
By the way, you have two small errors in your XML file:
The <MyApplication.Properties.Settings> element in incorrectly closed with </VASI_Application.Properties.Settings>
The <value> element is not correctly closed with </value>
Don't you have the property ConnectionString?
As documented here, usually you can access it in this way:
var setting = Properties.Settings.Default.ConnectionString;
By the way, your application tag starts with MyApplication.Properties.Settings but ends with VASI_Application.Properties.Settings
If you do actually want to go ahead with a custom config file section like in your example then you will need to follow this Microsoft guide for creating custom configuration sections.
https://msdn.microsoft.com/en-us/library/2tw134k3.aspx
If you get stuck following this guide then raise another question.

App.config - custom section not working

I recently started building a console version of a web application. I copied my custom sections from my web.config. to my app.config. When I go to get config information i get this error:
An error occurred creating the configuration section handler for x/y: Could not load type 'x' from assembly 'System.Configuration
The line that it is not liking is:
return ConfigurationManager.GetSection("X/Y") as Z;
Anyone run into something like this?
I was able to add
<add key="IsReadable" value="0"/>
in the appSettings and read it.
Addition:
I do actually have this defined about the custom section:
<configSections>
<sectionGroup name="x">
<section name="y" type="zzzzz"/>
</sectionGroup>
</configSections>
it sounds like your config-section handler is not defined
<configSection>
<section
name="YOUR_CLASS_NAME_HERE"
type="YOUR.NAMESPACE.CLASSNAME, YOUR.NAMESPACE, Version=1.1.0.0, Culture=neutral, PublicKeyToken=PUBLIC_TOKEN_ID_FROM_ASSEMBLY"
allowLocation="true"
allowDefinition="Everywhere"
/>
</configSection>
I had this identical issue recently. I created a custom sectiongroup for a web application(ran just fine), but when I ported this layer to a console app, the sectiongroup was failing.
You were correct in your question regarding how much of the "type" is required in your section definition. I've modified your configuration section with an example below:
<configSection>
<section
name="yourClassName"
type="your.namespace.className, your.assembly"
allowLocation="true"
allowDefinition="Everywhere" />
</configSection>
You'll notice, the type now has class name followed by assembly name. This is required for interaction outside of a web environment.
NOTE: Assembly name does not necessarily equal your namespace(for a given section).
If you want a custom config handler you have to define the class and reference it as shown by Steven Lowe. You can inherit from predefined handlers, or you can just use the value/key pair that is offered in appSetting section as you noted.
At the top of your file you require to have configSection tag with inside the section.
You can have sectionGroup too. Example:
<configuration>
<configSections>
<sectionGroup name="x">
<section name="y" type="a, b"/>
</sectionGroup>
<configSections>
</configuration>
This class works as a general custom configuration section handler for any type...
public class XmlConfigurator : IConfigurationSectionHandler
{
public object Create(object parent, object configContext, XmlNode section)
{
if (section == null) return null;
Type sectionType = Type.GetType((string)(section.CreateNavigator()).Evaluate("string(#configType)"));
XmlSerializer xs = new XmlSerializer(sectionType);
return xs.Deserialize(new XmlNodeReader(section));
}
}
In your app.config, add
<section name="NameofConfigSection" type="NameSpace.XmlConfigurator, NameSpace.Assembly"/>
And in the configuration section element, add an attribute to specify the type you want the root element deserialized into..
<?xml version="1.0" encoding="utf-8" ?>
<NameofConfigSection configType="NameSpace.NameofTypeToDeserializeInto, Namespace.Assembly" >
...
</NameofConfigSection>

Categories

Resources