Why controler does not go in to Create function? - c#

I have some custome section defined in seperate file, but when i call
ConfigurationManager.GetSection("Group/Group1/screen1")
controler does not go in to Create method and above code return null, whats wrong? anything is missing ?
web.Config:
<configSections>
<sectionGroup name="Group">
<section name="Group1" type="Handler"
allowLocation="true"
allowDefinition="Everywhere">
</section>
</sectionGroup>
</configSections>
<Group>
<Group1 configSource="folder1\custom.config" />
</Group>
Custom.config:
<?xml version="1.0"?>
<Group>
<Group1>
<Screen1>
<Property1>0</Property1>
<Property2>1</Property2>
</Screen1>
<Screen2>
<Property1>1</Property1>
<Property2>Create</Property2>
</Screen2>
</Group1>
<Group2>
<Screen1>
<Property1>0</Property1>
<Property2>1</Property2>
</Screen1>
<Screen2>
<Property1>1</Property1>
<Property2>Create</Property2>
</Screen2>
</Group2>
</Group>
Handler:
public class Handler: IConfigurationSectionHandler
{
public object Create(object parent, object configContext, XmlNode section)
{
**debugger**
// Some processing
// return object
}
}

I think your custom.config should start at the Group1 element, rather than the Group element, or the configSource should be applied to the Group. Either way, the root element of the referenced config file should be the same element type as configSource is applied to.
So, it sounds like what you want in your web.config is:
<Group configSource="folder1\custom.config" />
Whenever you use the configSource, the elements must match on both sides, e.g. if you have:
<Spargle configSource="place1.config" />
Then the root element of place1.config has to be a <Spargle>:
<?xml version="1.0"?>
<Spargle>
<Floom/>
</Spargle>

Related

app.config - configuration system failed to initialize with custom section

I've got a web api where I've added a custom section into the web.config as per this link: https://msdn.microsoft.com/en-us/library/2tw134k3.aspx. My web.config looks as follows:
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please
visit https://go.microsoft.com/fwlink/?LinkId=301879
-->
<configuration>
<configSections>
<sectionGroup name="productGroup">
<section
name="product"
type="myProject.Stuff.Api.ProductSection"
allowLocation="true"
allowDefinition="Everywhere"
/>
</sectionGroup>
</configSections>
<appSettings>
<!-- various app settings -->
</appSettings>
<productGroup>
<product name="my name" id="1" />
<product name="my name 2" id="2" />
</productGroup>
<!-- other standard elements -->
</configuration>
I added in the configSections and the productGroup. I then define a c# class as ProductSection as follows:
using System.Configuration;
namespace myProject.Stuff.Api
{
public class ProductSection : ConfigurationSection
{
[ConfigurationProperty("name", IsRequired = true)]
public string Name
{
get
{
return (string)this["name"];
}
set
{
this["name"] = value;
}
}
[ConfigurationProperty("id", IsRequired = true)]
public int Id
{
get
{
return (int)this["id"];
}
set
{
this["id"] = value;
}
}
}
}
I've copied the 2 sections across to my app.config in my test project, but when I now try and debug a test I get the failed to initialize error. When I comment out the productGroup section it then stops complaining. What have I done wrong?
UPDATE
As a side note I ended up structuring it a little more simply. As my 'product' sections only needed a name and id they lent themselves to key value pairs as per appSettings. So I created a section like this:
<configSections>
<section name="productGroup"
type="System..Configuration.NameValueSectionHandler"
allowLocation="true"
allowDefinition="Everywhere"/>
</configSections>
Note that I changed the type. My productGroup then looked like this:
<productGroup>
<add key="product1" value="1" />
<add key="product2" value="2" />
</productGroup>
I then could remove the ProductSection class altogether and just reference my group of products like this:
var products = ConfigurationManager.GetSection("productGroup") as NameValueCollection;
if (products.AllKeys.Contains(myProduct))
{
var myValue = products[myProduct];
}
I notice 2 things
A configuration section can only appear 1 time within a configuration file.
The full initialization exception shows:
System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize --->
System.Configuration.ConfigurationErrorsException: Sections must only appear once per config file.
This means you can only have 1 product section:
<productGroup>
<product name="my name" id="1" />
</productGroup>
If you need multiple, you need to declare multiple sections with unique section names:
<configuration>
<sectionGroup name="productGroup">
<section name="product" type="myProject.Stuff.Api.ProductSection" />
<section name="product2" type="myProject.Stuff.Api.ProductSection" />
</sectionGroup>
<!-- Other configuration elements -->
<productGroup>
<product name="my name" id="1" />
<product2 name="my name 2" id="2" />
</productGroup>
</configuration>
It is a best practice to declare the section in app/web.config with its fully qualified assemblyname,
which includes the name of the assembly (without file extension).
This is a must if the class/section is defined in an external assembly; here ProductionSection is defined in an assembly other than the one of the main unittest.
Declare the section as below in the App.config file of your unittest project.
(Replace NameOfTheAssemblyContainingTheProductSectionClass with the name of your assembly.)
<section
name="product"
type="myProject.Stuff.Api.ProductSection, NameOfTheAssemblyContainingTheProductSectionClass"
/>

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.

Getting section filtering to xml attribute

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.

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