Getting section filtering to xml attribute - c#

I want to select SMS section block according to tip attribute of SMS xml.
Currently: ConfigurationManager.GetSection("Logger/Sms") works but is there any way to get section like ConfigurationManager.GetSection("Logger/Sms[#tip='VF']")?
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="Logger">
<section name="Sms" type="caSectionTest.LogHandler, caSectionTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</sectionGroup>
</configSections>
<Logger>
<Sms tip="Clickatell">
<icerik>Soğuk zincir uygulamasından gönderilen sms</icerik>
<telNo>9053123123123</telNo>
<api>3363050</api>
<user>pkUser</user>
<pass>passhm</pass>
</Sms>
<Sms tip="Vodafone">
<icerik>write something into sms</icerik>
<telNo>905123123123</telNo>
<originator>336123</originator>
<user>ctUser</user>
<pass>9Mdfpass</pass>
</Sms>
</Logger>
</configuration>

You've probably long since moved on, but I created an XPath lookup for xml XElement recently available here: https://github.com/ChuckSavage/XmlLib/ If you want to use jsobo's comment to get the information you want.
You would use it like:
XElement root = XElement.Load(file);
XElement sms = root.XPathElement("//Sms[#tip={0}]", "VF"); // or "//Sms[#tip='VF']"
By using it with string.Format() syntax, you pass the type to the XPath as well, if you wanted to do a DateTime check, etc. I also find it easier for variable injections as well, instead of "//Sms[#tip='" + variable + "']". XPathElement is just XPath().FirstOrDefault() to return a single element.

Related

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.

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.

Read/Write to xml that was generated using csd

I've used the Configuration Section Designer (csd) to generate an xml configuration file to my application.
Now, I want to work with this xml file (on c#) and do 2 things:
1. read a specific value (searching by its field), something like
txtbox_username.Text = ConfigurationManager.AppSettings["userName"];
2. write a specific value, something like
config.AppSettings.Settings["userName"].Value = txtbox_username.Text;
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("configuration");
p.s: this is how i perform read/write for regular xml files that looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
add key="userName" value="Value1"
</appSettings>
</configuration>
but the csd generated xml looks different...
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="sectionName" type="Sample.ConfigurationSection.sectionName, Sample.ConfigurationSection, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</configSections>
<sectionName xmlns="Sample.ConfigurationSection">
<logFile debugLevel="3" filePath="c:\new" maxFileCount="10" maxFileLength="1000"/>
<results path="C:\Results"/>
<details user="blabla" pass="12345" code="abc"/>
<stuff fromAddress="from#gmail.com" toAddress="to#gmail.com" sendMail="true""/>
</sectionName>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
here, I want to edit and save, for example, user/pass/code fields.
In short (and using these extensions: http://searisen.com/xmllib/extensions.wiki) you can do this to read/write the user,
XElement file = XElement.Load(xmlFile);
XNamespace ns = "Sample.ConfigurationSection";
XElement section = file.GetElement(ns + "sectionName");
string user = section.Get("details/user", string.Empty);
section.Set("details/user", "bubba", true); // true = set as attribute
file.Save(xmlFile);

GetSection object cannot be cast to IDictionary<>

I hope I'm just missing something simple. I need to read/write to a section of my exe.config file. I have this in my code:
var appConfiguration = ConfigurationManager.OpenExeConfiguration("Mytest.Console.exe");
var fileEnvironment = appConfiguration.GetSection("fileEnvironment");
and this is my app.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="fileEnvironment" type="System.Configuration.DictionarySectionHandler"/>
</configSections>
<fileEnvironment>
<add key="TestEntry1" value="A nice value"/>
<add key="TestEntry2" value="Another value"/>
</fileEnvironment>
</configuration>
My appConfiguration variable is returned as {System.Configuration.Configuration} and the "HasFile" property is set to true.
Without casting my variable "fileEnvironment" is returned as System.Configuration.DefaultSection. When I add as IDictionary<string, string> to the GetSection method fileEnvironment is null.
Any ideas?
I kept researching the dictionary issue and came up with this stackoverflow Q&A! It produces a collection instead of a dictionary, but points the way to a solution. Thanks for everyone's time.
According to this old article, when a section is implemented using DictionarySectionHandler, ConfigurationManager.GetSection() will return a non-generic IDictionary, and not an IDictionary<T,V>. That's why your cast failed.
Although in modern times, it looks like it actually returns a HashTable.

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