Extend an element in App.config - c#

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).

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"];

How to deal with changed ConfigurationSection-Definition?

I have a Configuration-File that I read with the ConfigurationManager. There are some Sections that I defined by myself.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="applicationWideSettingsSection" type="MyTestApp.ApplicationSettings.ApplicationWideSettingsSection, MyTestAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</configSections>
<applicationWideSettingsSection>
<pathToSomeFile value="C:\Users\..." />
</applicationWideSettingsSection>
</configuration>
There are new requirements: now I have to store another value in the applicationWideSettingsSection like this:
<applicationWideSettingsSection>
<pathToSomeFile value="C:\Users\..." />
<pathToSomeOtherFile value="C:\Programs\..." />
</applicationWideSettingsSection>
So I change my definition of the applicationWideSettingsSection. If I now run the application with an old config-File it throws an exception on this line:
var configSection = _config.GetSection("applicationWideSettingsSection");
because there is only the pathToSomeFile-Setting and the other one is missing.
Is there a way to manually add another (default value) to this section?
How would you deal with this??
Thanks in advance, Joerg
Because I didn't want to change my design away from my custom Setting-Types I found a different way:
I set the IsRequired to false so no exception is thrown when the setting is missing. If it's missing I set it to some value from code.
In a different approach I wanted to override some of the Configuration-Section methods but did not get it to work...
now I have to store another value in the applicationWideSettingsSection
Instead of your custom type ApplicationWideSettingsSection you can use a key-value pairs, so
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="applicationWideSettingsSection"
type="System.Configuration.NameValueSectionHandler" />
</configSections>
<applicationWideSettingsSection>
<pathToSomeFile value="C:\Users\..." />
</applicationWideSettingsSection>
</configuration>
This will store 1 or many parameters and allow you to enumerate on the inner parameters. You can also try DictionarySectionHandler. I found sample code in this post.

Can't get app.config value "connectionStrings"?

I am writing a program in visual studio,now i can't get the value of app.config.My app.config look like this:
<?xml version="1.0"?>
<configuration>
<connectionStrings>
<add name="connStr" connectionString="Data Source=Dolphin-PC;Initial Catalog=jsptpd_SYS;Persist Security Info=True;User ID=sa;Password=ccir"/>
</connectionStrings>
</configuration>
And the code i am try to get the value:
try
{
con2 = System.Configuration.ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
logger.Info("try to get connectionstr success:" + connStr);
}
catch(Exception ex)
{
logger.Info("try to get connectionstr failed:" + ex.ToString());
}
The log's output:
2013-12-14 16:22:28,710 [1] INFO ApplicationInfoLog [(null)] <(null)>
- try to get connectionstr failed:System.NullReferenceException:
object reference not set to instance.
on Jsptpd.JobScheduler.jsptpdJobScheduler..ctor()
location D:\jsptpd\Code\jsptpdJobScheduler\jsptpdJobScheduler\jsptpdJobShedule.cs:line 46
Where is wrong? Why can't read the ConnectionStrings?
Your section is declared as NameValueSectionHandler. As this article points out, this handler returns a NameValueCollection, not the IDictionary that you cast it to afterwards. That's why as IDictionary results in a null value.
Either declare your section as DictionarySectionHandler or change IDictionary to NameValueCollection.
If that config you posted is really what you have, then that config is just plain wrong.... you have two nested <configuration> sections - that won't ever work!
If your config really looks like what you posted, you need to change it to look like this:
<?xml version="1.0"?>
<configuration> <!-- one and ONLY one <configuration> node! -->
<configSections> <!-- directly under <configuration> -->
<section name="quartz" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<configSections>
<connectionStrings> <!-- directly under <configuration> -->
<add name="connStr" connectionString="Data Source=Dolphin-PC;Initial Catalog=jsptpd_SYS;Persist Security Info=True;User ID=sa;Password=ccir"/>
</connectionStrings>
<quartz> <!-- directly under <configuration> -->
...........
</quartz>
<appSettings> <!-- directly under <configuration> -->
<add key="connStr" value="Data Source=Dolphin-PC;Initial Catalog=jsptpd_SYS;Persist Security Info=True;User ID=sa;Password=ccir"/>
</appSettings>
</configuration>
There should be only one <configuration> section, and all other tags, like <configSections>, <quartz>, <connectionStrings> and <appSettings> should be directly inside the one and only <configuration> element
Check your app.config file attribute set,make sure that Generate Operation is not embeded resource.
Because you read the app.config through ConfiguationManager class,the Configuration read file like this:
http://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.aspx
•Read and write configuration files as a whole. Your application can read and write configuration settings at any level, for itself or for other applications or computers, locally or remotely. Use one of the methods provided by the ConfigurationManager class to open a configuration file such as SampleApp.exe.config. These methods return a Configuration object that in turn exposes methods and properties you can use to work with the associated configuration files. The methods perform read or write operations and create the configuration data every time that a file is written.
If you set embeded resource,the bin directionary could not generate the SampleApp.exe.config file,so the ConfigurationManager could read your config file.
So if you want to correct the problem,do this
choose the app.config file in resource manager of visual studio:
set the copy to outout dirctionary to:
No copy
set the generte operation to:
None
The problem will fixed.

Merge .net configuration files

My application has 2 config files at the moment.
App.config
Custom.config
The App.config references the Custom.config via a custom section handler like below:
<configuration>
<configSections>
<section name="Custom" type="MyApp.CustomConfigSection, MyApp" />
</configSections>
<Custom configSource="Custom.config" />
</configuration>
The problem is the Custom.config file contains a single section with many elements. I'd like to split this out so some of the elements are in one file and some are in another.
e.g. Right now I have
'<Custom>
<Group1 ../>
<Group2 ../>
<Group3 ../>
</Custom>
I'd like to make 2 or more files like below.
'<Custom>
<Group1 ../>
</Custom>'
'<Custom>
<Group2 ../>
<Group3 ../>
</Custom>'
At the moment I call ConfigurationManager.GetSection("Custom") as MyCustomConfigSection. I then have a number of classes with various configuration attributes that are populated automatically by the .net configuration.
Is there a way to do this split or can you not split 1 section into multiple files?
Thanks in advance

create your own settings in xml

I'm in a ASP.NET project where I need to give several parameters to the administrator that is going to install the website, like:
AllowUserToChangePanelLayout
AllowUserToDeleteCompany
etc...
My question is, will be a good thing to add this into the web.config file, using my own configSession or add as a profile varibles? or should I create a XML file for this?
What do you do and what are the cons and favs?
I originally thought about web.config but I then realized that I should mess up with Website configurations and my own web app configuration and that I should create a different file, them I read this post and now I'm on this place... should I do this or that?
I usually use Settings - available via the project properties - Settings. These can be edited and saved in code, and I write a form / web page to edit them.
If you want to use the XML configuration, there's an attribute called file that reads external files.
You could have a web.config file and a someothername.config file. The someothername.config would have settings like:
<appSettings>
<add key="ConnString" value="my conn string" />
<add key="MaxUsers" value="50" />
</appSettings>
And the web.config would have
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings file="ExternalWeb.config">
<add key="MyKey" value="MyValue" />
</appSettings>
</configuration>
See DevX for the example I stole.
just to let you guys know that I did what configurator recommended but with a twist.
instead of asking all the time (that I need) for
System.Configuration.ConfigurationManager.AppSettings["myKey"];
I just created a static class that would pull this values with what we call by Strongly typed values (so you don't need to remember all the values)
the mySettings class
public static class mySettings
{
public enum SettingsType
{ UserPermitions, WebService, Alerts }
public enum SectionType
{ AllowChangeLayout, AllowUserDelete, MaximumReturnsFromSearch, MaximumOnBatch, SendTo }
public static String GetSettings(SettingsType type, SectionType section)
{
return
ConfigurationManager.AppSettings[
String.Format("{0}_{1}",
Enum.Parse(typeof(SettingsType), type.ToString()).ToString(),
Enum.Parse(typeof(SectionType), section.ToString()).ToString())
];
}
}
the web.config appSettings part
<configuration>
<appSettings file="myApp.config">
<add key="UserPermitions_AllowChangeLayout" value="" />
<add key="UserPermitions_AllowUserDelete" value="" />
<add key="WebService_MaximumReturnsFromSearch" value="" />
<add key="Alerts_SendTo" value="" />
<add key="Alerts_MaximumOnBatch" value="" />
</appSettings>
</configuration>
the entire myApp.config file
<?xml version="1.0" encoding="utf-8" ?>
<!--
###
### This file serves the propose of a quick configuration.
### Administrator can either change this values directly or use the
### Settings tab in the application.
###
-->
<appSettings>
<!-- *** User Access Configuration *** -->
<!-- Allow user to change the panels layout {1: Yes} {0: No} -->
<add key="UserPermitions_AllowChangeLayout" value="1" />
<!-- Allow user to delete a company fro monitoring -->
<add key="UserPermitions_AllowUserDelete" value="1" />
<!-- *** Web Service configuration *** -->
<!-- Maximum responses from the search service -->
<add key="WebService_MaximumReturnsFromSearch" value="10" />
<!-- *** Allerts configuration *** -->
<!-- Send the alerts to the email writeen below -->
<add key="Alerts_SendTo" value="bruno.in.dk#gmail.com" />
<!-- Send an alert when user import more than the number bellow -->
<add key="Alerts_MaximumOnBatch" value="10" />
</appSettings>
So, now I call like this:
p.value = mySettings.GetSettings(
mySettings.SettingsType.WebService,
mySettings.SectionType.MaximumReturnsFromSearch);
Hope that helps someone with the same problem :)
You may also put your configurations in a settings file. In your project, open Properties and go to Settings which looks
like so
To access the values in your code, use Properties.Settings.YourSettingName;
Use Properties.Settings.Default.Reload(); to refresh your settings during runtime

Categories

Resources