Custom app.config section fails to cast to NameValueCollection - c#

This tutorial makes what I'm trying to do look dead easy. All I want to do is read a custom attribute out of my web.config. Here's the relevant part:
<configSections>
<section name="Authentication.WSFedShell" type="System.Configuration.DictionarySectionHandler, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</configSections>
<Authentication.WSFedShell>
<add key="Authentication.PrincipalType" value="ClientCertificate" />
</Authentication.WSFedShell>
In the immediate window I can execute:
System.Configuration.ConfigurationManager.GetSection("Authentication.WSFedShell")
which returns the string
["Authentication.PrincipalType"]: "ClientCertificate"
However, when I try to cast it (with as NameValueCollection), as this tutorial says to do, I get null returned and my code blows up. There's gotta be a cleaner way to get the value "ClientCertificate" than manually parsing the string result.
How do I read "ClientCertificate" from app.config?

Why can't you use AppSetting like
<configuration>
<appSettings>
<add key="Authentication.PrincipalType" value="ClientCertificate"/>
</appSettings>
</configuration>
System.Configuration.ConfigurationManager.AppSettings["Authentication.PrincipalType"]
Most probably the issue with your section is the Type attribute. But anyways, you need to cast the result of GetSection() to your type defined for section like
System.Configuration.DictionarySectionHandler config = (System.Configuration.DictionarySectionHandler)System.Configuration.ConfigurationManager.GetSection("Authentication.WSFedShell");

Related

Web.Config custom section returns null

Well I have following entries in my web config for SagePay Integration in an ASP.net MVC project.
<configuration>
<configSections>
<section name="SagePayConfiguration" type="System.Configuration.IgnoreSectionHandler" requirePermission="true" restartOnExternalChanges="true" allowLocation="true"/>
</configSections>
<SagePayConfiguration>
<!--Mandatory
Set to TEST for the Test Server and LIVE for the live environment-->
<add key="sagepay.api.env" value="TEST" />
.
.
</SagePayConfiguration>
However I am getting null when trying to access it from C# code.
SagePayConfiguration sagePayConfiguration = (SagePayConfiguration)System.Configuration.ConfigurationManager.GetSection("SagePayConfiguration");
Any help what I am missing here?
You must cast the ConfigrationItem to "System.Configuration.IgnoreSectionHandler" or set the type Attribute in web.conf to an existing Type in your assembly.
<section name="<SectionName>" type="<your type (FQN)>, <Assembly>" />
After that you can access it
YourType o = ((YourType)ConfigurationManager.GetSection("sectionName"));
EDIT:
The Type must derive from ConfigurationSection.

Add More than One Custom Sections to App Config C#?

I would like to make an app.config that looks like
<configuration>
<SQLconneciton>
<add key=name/>
<add key= otherStuff/>
</SQLconnection>
<PacConnection>
<add key=name/>
<add key= otherStuff/>
</PacConnection>
</configuration>
I've read many examples where people make ONE custom section and add stuff, I need to allow the user to add multiple sections, read, delete. I don't really need fancy elements, just simple add and key values. Is section groups worth using or is there something easy I'm missing?
Sure - there's really nothing stopping you from creating as many custom config sections as you liked!
Try something like this:
<?xml version="1.0"?>
<configuration>
<!-- define the config sections (and possibly section groups) you want in your config file -->
<configSections>
<section name="SqlConnection" type="System.Configuration.NameValueSectionHandler"/>
<section name="PacConnection" type="System.Configuration.NameValueSectionHandler"/>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
<!-- "implement" those config sections as defined above -->
<SqlConnection>
<add key="abc" value="123" />
</SqlConnection>
<PacConnection>
<add key="abc" value="234" />
</PacConnection>
</configuration>
The System.Configuration.NameValueSectionHandler is the default type to use for a config section that contains <add key="...." value="....." /> entries (like <appSettings>).
To get the values, just use something like this:
NameValueCollection sqlConnConfig = ConfigurationManager.GetSection("SqlConnection") as NameValueCollection;
string valueForAbc = sqlConnConfig["abc"];
And you can absolutely mix and match existing section handler types as defined by .NET as well as your own custom config sections, if you've defined some of those yourself - just use whatever you need!

Edit App.Config name-value pairs from a separate tool

I am trying to create a simple tool for a service person to update a few entries in the App.Config of a different program. The App.Config file contains custom parameters used upon initialization of our program.
Since the App.Config contains many sensitive items a tool is needed to ensure only certain parameters are changed. Thus, the reason not to allow them to edit the App.Config directly.
My questions:
How can I access the name-value pairs from the config sections of an App.config from a separate program?
Which is better suited for the UI: Winforms or WPF? Are their controls that make it easy to add more entries in the future?
The tool should allow the user to set either a String, int, double or Boolean.
Here is the structure of the App.Config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="Settings">
<section name="Section1" type="System.Configuration.NameValueSectionHandler"/>
<section name="Section2" type="System.Configuration.NameValueSectionHandler"/>
<section name="Section3" type="System.Configuration.NameValueSectionHandler"/>
<section name="Section4" type="System.Configuration.NameValueSectionHandler"/>
</sectionGroup>
</configSections>
<Settings>
<Section1>
<add key="NAME_STRING" value="Some String"/>
</Section1>
<Section2>
<add key="NAME_INTEGER" value="10"/>
</Section2>
<Section3>
<add key="NAME_DOUBLE" value="10.5"/>
</Section3>
<Section4>
<add key="NAME_BOOLEAN" value="true"/>
</Section4>
</Settings>
... Omitted ...
</configuration>
In the program which uses the App.Config itself, I can easily change the values like so:
NameValueCollection nvc = (NameValueCollection)ConfigurationManager.GetSection("Settings/Section1");
Is there a similar way to do this from a separate program after loading the App.Config?
An answer to Question 1: An app.config file is an XML file. It might be easiest to load it as an XML document and modify that programmatically, followed by a save, than to use System.Configuration classes.
ETA: I believe it can be done with ConfigurationManager. Look at the OpenMappedExeConfiguration method. There's a good example there.
You could treat the app.config file as a normal XML file. Use either XDocument or XmlDocument to load the file.
Then use XPath or Linq to XML to find the name-value pairs.
As for Windows.Forms vs. WPF, its a design decision. Both have good and bad points.
[Update]
If you still want to use System.Configuration, you can use the ConfigurationManager.OpenExeConfiguration to get access to the other program's app.config file. This returns a Configuration object, which has a GetSection method.

web.config c# .net web application

How to read a personal section in a web.config ?
<MyPersonalSection>
<add name="toto" enable="true" URL="http://localhost:43242" />
<add name="titi" enable="false" URL="http://localhost:98762" />
<MyPersonalSection/>
I'd like to get the enable value and/or URL value with the name value.
I also have this mistake : Unrecognized configuration section MyPersonalSection
I been trying
var config = ConfigurationManager.GetSection("MyPersonalSection");
Here is a cool example for that.
You don't need to write a custom configuration handler to get what you want. There are built-in configuration handlers that you can use if you simply want key-value entries. But, you'll have to use key instead of name and value instead of URL. For example:
<configuration>
<configSections>
<section name="MyPersonalSection" type="System.Configuration.NameValueSectionHandler" />
</configSections>
<MyPersonalSection>
<add key="toto" value="http://localhost:43242" />
<add key="titi" value="http://localhost:98762" />
</MyPersonalSection>
</configuration>
And you can access them via code:
var myValues = ConfigurationSettings.GetConfig("MyPersonalSection") as NameValueCollection;
var url = myValues["toto"];
I would suggest naming your keys in a way that makes it clear what the value should be, like "totoUrl" and "titiUrl".
If you want something other than string value pairs, you'll have to write your own custom handler.
You can add appSettings section in your web.config with key that you will need. For example:
<configuration>
<appSettings>
<add key="FirstUrl" value="http://localhost:43242"/>
<add key="SecondUrl" value="http://localhost:98762" />
</appSettings>
...
</configuration>
So, since aspx.cs file, you can declare directive
using System.Configuration;
And later, you can retrieve FirstUrl value in this way:
var myUrl = ConfigurationManager.AppSettings["FirstUrl"];

When are settings from app.config actually read?

When are settings from app.config actually read by application?
Suppose I have a windows service and some app settings for it. In code I have a method where some setting is used. Method is being called in every iteration, not just once during all the time. If I change the setting value through the configuration file should I restart the service for it to be "refreshed" inside or will it be accepted the next time without any interaction from my side?
You need to call ConfigurationManager.RefreshSection method to get the latest values read directly from disk. Here's a simple way to test and provide answer to your question:
static void Main(string[] args)
{
while (true)
{
// There is no need to restart you application to get latest values.
// Calling this method forces the reading of the setting directly from the config.
ConfigurationManager.RefreshSection("appSettings");
Console.WriteLine(ConfigurationManager.AppSettings["myKey"]);
// Or if you're using the Settings class.
Properties.Settings.Default.Reload();
Console.WriteLine(Properties.Settings.Default.MyTestSetting);
// Sleep to have time to change the setting and verify.
Thread.Sleep(10000);
}
}
My app.config containing:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="ConsoleApplication2.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<appSettings>
<add key="myKey" value="Original Value"/>
</appSettings>
<userSettings>
<ConsoleApplication2.Properties.Settings>
<setting name="MyTestSetting" serializeAs="String">
<value>Original Value</value>
</setting>
</ConsoleApplication2.Properties.Settings>
</userSettings>
</configuration>
After you start the application, open the app.config within the build folder, and change the value of the appSetting "myKey". You'll see the new value printed out to the console.
To answer the question, yes they are cached on the first time they are each read I think, and to force the read straight from the disk, you need to refresh the section.
Either when you load it up via the configuration manager (ConfigurationManager.GetSection("x/y");) or when you try to access the properties.
There is a slight grey area here because when you get the configuration out via the config manager:
var config = (MyConfigSection)ConfigurationManager.GetSection("MyConfigSection");
You get a configuration object back if you have provided the configuration section type in the configurationSections element at the top of the config file. If you do not actually provide the actual config you will still get an object back.
However if you have a required field that is not set it will not throw an exception till you call the property. I have worked this out whilst trying to unit test my custom configuration sections.

Categories