I have a small app that searches my SQL Server database for the given value in all of the fields where it could be used. Part of that is a custom app.config section to hold all of these fields. However I'm getting an error on this line in the app:
var section = (DatabaseFieldSection)ConfigurationManager.GetSection("DatabaseFields");
app.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="DatabaseFields" type="PartyFinder.DataAccess.DatabaseFieldSection, DataAccess"/>
</configSections>
<connectionStrings>
<!-- Data removed for security purposes -->
</connectionStrings>
<DatabaseFields>
<add Key="Person.FirstName (SV)" TableName="dbo.Person" ColumnName="FirstName" FieldType="SV" />
</DatabaseFields>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>
Classes:
using System;
using System.Configuration;
namespace PartyFinder.DataAccess
{
public class DatabaseFieldElement : ConfigurationElement
{
[ConfigurationProperty("Key", IsKey = true, IsRequired = true)]
public string Key
{
get { return (string)base["Key"]; }
}
[ConfigurationProperty("TableName", IsKey = false, IsRequired = true)]
public string TableName
{
get { return (string)base["TableName"]; }
}
[ConfigurationProperty("ColumnName", IsKey = false, IsRequired = true)]
public string ColumnName
{
get { return (string)base["ColumnName"]; }
}
[ConfigurationProperty("FieldType", IsKey = false, IsRequired = true)]
public string FieldType
{
get { return (string)base["FieldType"]; }
}
}
public class DatabaseFieldSection : ConfigurationSection
{
[ConfigurationProperty("DatabaseFields", IsDefaultCollection = true)]
[ConfigurationCollection(typeof(DatabaseFieldCollection), AddItemName = "add", ClearItemsName = "clear", RemoveItemName = "remove")]
public DatabaseFieldCollection DatabaseFields
{
get { return ((DatabaseFieldCollection)base["DatabaseFields"]); }
}
}
public class DatabaseFieldCollection : ConfigurationElementCollection
{
internal const string PropertyName = "Fields";
public override ConfigurationElementCollectionType CollectionType
{
get
{
return ConfigurationElementCollectionType.AddRemoveClearMap;
}
}
protected override string ElementName
{
get
{
return PropertyName;
}
}
protected override bool IsElementName(string elementName)
{
return elementName.Equals(PropertyName, StringComparison.InvariantCultureIgnoreCase);
}
public override bool IsReadOnly()
{
return false;
}
protected override ConfigurationElement CreateNewElement()
{
return new DatabaseFieldElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((DatabaseFieldElement)(element)).Key;
}
public DatabaseFieldElement this[int id]
{
get
{
return (DatabaseFieldElement)BaseGet(id);
}
}
}
}
I have done a ton of searches and nothing has worked so far. Any advice is much appreciated!
I managed to get the following to work in a console app by adding a parent DatabaseConfig node:
The DatabaseFieldSection class:
public class DatabaseFieldSection : ConfigurationSection
{
public static DatabaseFieldSection GetConfig()
{
return (DatabaseFieldSection)System.Configuration.ConfigurationManager.GetSection("DatabaseConfig") ?? new DatabaseFieldSection();
}
[System.Configuration.ConfigurationProperty("DatabaseFields")]
[ConfigurationCollection(typeof(DatabaseFieldCollection), AddItemName = "add")]
public DatabaseFieldCollection DatabaseFields
{
get
{
object o = this["DatabaseFields"];
return o as DatabaseFieldCollection;
}
}
}
And the App.config:
<configSections>
<section name="DatabaseConfig" type="TestEnvironment.DBConfig.DatabaseFieldSection, TestEnvironment"/>
</configSections>
<DatabaseConfig>
<DatabaseFields>
<add Key="Person.FirstName (SV)" TableName="dbo.Person" ColumnName="FirstName" FieldType="SV" />
</DatabaseFields>
</DatabaseConfig>
Usage:
var config = DatabaseFieldSection.GetConfig();
It seems as though the config <section /> cannot be the same as the config element collection name. e.g DatabaseFields, it needs to be:
Section > Collection > Items
Or:
DatabaseConfig > DatabaseFields > add
Related
I am getting following exception when I run the code:
FileNotFoundException: Could not load file or assembly 'My' or one of its dependencies. The system cannot find the file specified.
Following is my app.config:
<configuration>
<configSections>
<section name="registerCompanies" type="My.MyConfigSection, My" />
</configSections>
<registerCompanies>
<add name="Tata Motors" code="Tata"/>
<add name="Honda Motors" code="Honda"/>
</registerCompanies>
</configuration>
Following is my namespace and class:
using System.Configuration;
using System.Linq;
namespace My
{
public class MyConfigSection : ConfigurationSection
{
[ConfigurationProperty("", IsRequired = true, IsDefaultCollection = true)]
public MyConfigInstanceCollection Instances
{
get { return (MyConfigInstanceCollection)this[""]; }
set { this[""] = value; }
}
}
public class MyConfigInstanceCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new MyConfigInstanceElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
//set to whatever Element Property you want to use for a key
return ((MyConfigInstanceElement)element).Name;
}
public new MyConfigInstanceElement this[string elementName]
{
get
{
return this.OfType<MyConfigInstanceElement>().FirstOrDefault(item => item.Name == elementName);
}
}
}
public class MyConfigInstanceElement : ConfigurationElement
{
//Make sure to set IsKey=true for property exposed as the GetElementKey above
[ConfigurationProperty("name", IsKey = true, IsRequired = true)]
public string Name
{
get { return (string)base["name"]; }
set { base["name"] = value; }
}
[ConfigurationProperty("code", IsRequired = true)]
public string Code
{
get { return (string)base["code"]; }
set { base["code"] = value; }
}
}
}
I am trying to retrieve the app.config using the below code:
MyConfigSection config = ConfigurationManager.GetSection("registerCompanies") as MyConfigSection;
Console.WriteLine(config.Instances["Honda Motors"].Code);
foreach (MyConfigInstanceElement e in config.Instances)
{
Console.WriteLine("Name: {0}, Code: {1}", e.Name, e.Code);
}
The only reason I think it's not working is may be because my namespace My is in another .cs file ConfigSetup.cs and I am trying to retrieve the appconfig in another .cs file.
I am not sure how to address in the below line that My.MyCofigSection exists in ConfigSetup.cs and the project name is FileManager if I need to include that as well ? Below line gives me an exception that I mentioned above.
<section name="registerCompanies" type="My.MyConfigSection, My" />
I have changed type="My.MyConfigSection, My" to type="My.MyConfigSection, File_Manager" and it worked thank you very much
I am trying to create a custom section in my web.config. I have a custom class and a declaration section in my web.config.
when I run my code however I am getting this error "...does not inherit from System.Configuration.IConfigurationSectionHandler'."
MSDN documentation states that this Interface is now deprecated.
I don't understand what cold be happening.
FYI I used this (http://blogs.perficient.com/microsoft/2017/01/4-easy-steps-to-custom-sections-in-web-config/ as my guide to create my custom section.
Here is my web.config
<configuration>
<configSections>
<section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" />
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<section name ="BDKConfigs" type="SPS.CardDecryption.Services.BDKConfigs" allowLocation="true" allowDefinition="Everywhere" />
</configSections>
Here is my custom section in the web.config
<BDKConfigs>
<!--collection-->
<BDK>
<!--elements-->
<add name="IDTechPublicBDK" value="0123456789ABCDEFFEDCBA9876543210"/>
<add name="IDTechProdBDK" value=""/>
</BDK>
</BDKConfigs>
this is my custom class
using System.Configuration;
namespace myNameSpace
{
//This class reads the defined config section (if available) and stores it locally in the static _Config variable.
public class BDKConfigs
{
public static BDKConfigsSection _Config = ConfigurationManager.GetSection("BDKConfigs") as BDKConfigsSection;
public static BDKElementCollection GetBDKGroups()
{
return _Config.BDKConfigs;
}
}
public class BDKConfigsSection : ConfigurationSection
{
//Decorate the property with the tag for your collection.
[ConfigurationProperty("BDK")]
public BDKElementCollection BDKConfigs
{
get { return (BDKElementCollection)this["BDK"]; }
}
}
//Extend the ConfigurationElementCollection class.
//Decorate the class with the class that represents a single element in the collection.
[ConfigurationCollection(typeof(BDKElement))]
public class BDKElementCollection : ConfigurationElementCollection
{
public BDKElement this[int index]
{
get { return (BDKElement)BaseGet(index); }
set
{
if (BaseGet(index) != null)
BaseRemoveAt(index);
BaseAdd(index, value);
}
}
protected override ConfigurationElement CreateNewElement()
{
return new BDKElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((BDKElement)element).Name;
}
}
//Extend the ConfigurationElement class. This class represents a single element in the collection.
//Create a property for each xml attribute in your element.
//Decorate each property with the ConfigurationProperty decorator. See MSDN for all available options.
public class BDKElement : ConfigurationElement
{
[ConfigurationProperty("name", IsRequired = true)]
public string Name
{
get { return (string)this["name"]; }
set { this["name"] = value; }
}
[ConfigurationProperty("queryString", IsRequired = false)]
public string Value
{
get { return (string)this["Value"]; }
set { this["Value"] = value; }
}
}
}
The issue was that I had the wrong type specified in the web.config. When I changed my web.config to
type="SPS.CardDecryption.Services.BDKConfigsSection , worked like a charm.
I have updated answer:
public class BDKConfigsSection : ConfigurationSection
{
[ConfigurationProperty("BDK")]
public BDKElementCollection BDKConfigs
{
get { return (BDKElementCollection) base["BDK"]; }
}
}
[ConfigurationCollection(typeof(BDKElement))]
public class BDKElementCollection : ConfigurationElementCollection
{
public BDKElement this[int index]
{
get { return (BDKElement)BaseGet(index); }
set
{
if (BaseGet(index) != null)
BaseRemoveAt(index);
BaseAdd(index, value);
}
}
protected override ConfigurationElement CreateNewElement()
{
return new BDKElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((BDKElement)element).Name;
}
public override ConfigurationElementCollectionType CollectionType
{
get { return ConfigurationElementCollectionType.BasicMapAlternate; }
}
protected override string ElementName => "BDKItem";
}
public class BDKElement : ConfigurationElement
{
[ConfigurationProperty("name", IsRequired = true)]
public string Name
{
get { return (string)this["name"]; }
set { this["name"] = value; }
}
[ConfigurationProperty("queryString", IsRequired = false)]
public string Value
{
get { return (string)this["queryString"]; }
set { this["queryString"] = value; }
}
}
that one working fine :
<BDKConfigsSection>
<BDK>
<BDKItem name="IDTechPublicBDK" queryString="0123456789ABCDEFFEDCBA9876543210"/>
<BDKItem name="IDTechProdBDK" queryString=""/>
</BDK> </BDKConfigsSection>
I followed a tutorial on Stackoverflow to add a custom configuration section to my exe's config file, however on calling it, it is returning null. It's not even getting into the static constructors so something is clearly wrong, but I can't see what.
Here is my config file and the section I wish to find.
<configuration>
<appSettings>
</appSettings>
<configSections>
<section name="PresetFilters" type="ImageTool.PresetFiltersConfiguration, ImageTool" />
</configSections>
<PresetFilters>
<add key="Default,-20,0,0,0,0" />
<add key="No Change,0,0,0,0,0" />
<add key="Dark Photo,10,10,0,0,-10" />
</PresetFilters>
</configuration>
I call it like this:
PresetFiltersConfiguration pf = (PresetFiltersConfiguration)ConfigurationManager.GetSection("PresetFilters");
and it returns null and doesn't even enter my class or class statics. Here's the code. Any help would be appreciated. Thanks.
public class PresetFiltersConfiguration : ConfigurationSection
{
private static ConfigurationPropertyCollection properties;
private static ConfigurationProperty propPresets;
static PresetFiltersConfiguration()
{
propPresets = new ConfigurationProperty(null, typeof(PresetFiltersElementCollection),
null,
ConfigurationPropertyOptions.IsDefaultCollection);
properties = new ConfigurationPropertyCollection { propPresets };
}
protected override ConfigurationPropertyCollection Properties
{
get
{
return properties;
}
}
public PresetFiltersElementCollection PresetFilter
{
get
{
return this[propPresets] as PresetFiltersElementCollection;
}
}
}
public class PresetFiltersElementCollection : ConfigurationElementCollection
{
public PresetFiltersElementCollection()
{
properties = new ConfigurationPropertyCollection();
}
private static ConfigurationPropertyCollection properties;
protected override ConfigurationPropertyCollection Properties
{
get
{
return properties;
}
}
public override ConfigurationElementCollectionType CollectionType
{
get
{
return ConfigurationElementCollectionType.BasicMap;
}
}
protected override string ElementName
{
get
{
return "add";
}
}
protected override ConfigurationElement CreateNewElement()
{
return new PresetFiltersElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
var elm = element as PresetFiltersElement;
if (elm == null) throw new ArgumentNullException();
return elm.KeyName;
}
}
public class PresetFiltersElement : ConfigurationElement
{
private static ConfigurationPropertyCollection properties;
private static ConfigurationProperty propKey;
protected override ConfigurationPropertyCollection Properties
{
get
{
return properties;
}
}
public PresetFiltersElement()
{
propKey = new ConfigurationProperty("key", typeof(string),
null,
ConfigurationPropertyOptions.IsKey);
properties = new ConfigurationPropertyCollection { propKey };
}
public PresetFiltersElement(string keyName)
: this()
{
KeyName = keyName;
}
public string KeyName
{
get
{
return this[propKey] as string;
}
set
{
this[propKey] = value;
}
}
}
You need something like this in your app.config, otherwise the application won't know how to process your new section.
<configSections>
<sectionGroup name="pageAppearanceGroup">
<section
name="PresetFilters"
type="PresetFiltersConfiguration"
allowLocation="true"
allowDefinition="Everywhere"
/>
</sectionGroup>
</configSections>
After applying the fixes it worked, but the actual fault is to do with it not working for class libraries, and I've created a new question for this.
Thanks.
I am trying setting up application configuration. Problem is that nothing is readed from the configuration. I am using this code:
Sections:
public class TownSection : ConfigurationSection
{
public static TownSection.GetConfig()
{
return (TownSection)System.Configuration.ConfigurationManager
.GetSection("TownSection") ?? new TownSection();
}
[System.Configuration.ConfigurationProperty("TownProperties")]
[ConfigurationCollection(typeof(TownProperties), AddItemName = "TownProperty")]
public TownProperties TownProperties
{
get
{
object o = this["TownProperties"];
return o as TownProperties;
}
}
}
List of the entities:
public class TownProperties: ConfigurationElementCollection
{
public TownProperty this[int index]
{
get
{
return base.BaseGet(index) as TownProperty ;
}
set
{
if (base.BaseGet(index) != null)
{
base.BaseRemoveAt(index);
}
this.BaseAdd(index, value);
}
}
public new TownProperty this[string responseString]
{
get { return (TownProperty)BaseGet(responseString); }
set
{
if (BaseGet(responseString) != null)
{
BaseRemoveAt(BaseIndexOf(BaseGet(responseString)));
}
BaseAdd(value);
}
}
protected override System.Configuration.ConfigurationElement CreateNewElement()
{
return new TownProperty();
}
protected override object GetElementKey(System.Configuration.ConfigurationElement element)
{
return ((TownProperty)element).Name;
}
}
Entity:
public class TownProperty: ConfigurationElement
{
[ConfigurationProperty("Name", IsRequired = true)]
public string Name
{
get
{
return this["Name"] as string;
}
}
[ConfigurationProperty("Distance", IsRequired = true)]
public string Distance
{
get
{
return this["Distance"] as string;
}
}
}
Configuration in app.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="TownSection">
<section
name="TownSection"
type="App.Configurations.TownSection"
allowLocation="true"
allowDefinition="Everywhere" />
</sectionGroup>
</configSections>
<TownSection>
<TownProperties>
<TownProperty Name="A" Distance="1.8"/>
<TownProperty Name="B" Distance="5.8"/>
</TownProperties>
</TownSection>
in code:
var config = TownSection.GetConfig();
foreach(TownProperty item in config.TownProperties) /// cycle is skipped
{
Console.WriteLine(item.Name);
Console.WriteLine(item.Distance);
}
What could be the problem?
I've changed couple of things in xml and that works.
1.Removed Section group tag
2.Added assembly name in section tag's type attribute. In format (Full type name, Assembly name)
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section
name="TownSection"
type="App.Configurations.TownSection, App.Configurations"
allowLocation="true"
allowDefinition="Everywhere" />
</configSections>
<TownSection>
<TownProperties>
<TownProperty Name="A" Distance="1.8"/>
<TownProperty Name="B" Distance="5.8"/>
</TownProperties>
</TownSection>
</configuration>
I have a custom config which is based on some classes. My problem is that I get an error saying that a config element is unrecognized. The class is as follows:
[ConfigurationCollection(typeof(SectionItem), AddItemName = "Item", CollectionType = ConfigurationElementCollectionType.BasicMap)]
public class Sections : ConfigurationElementCollection
{
public SectionItem this[int index]
{
get { return BaseGet(index) as SectionItem; }
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}
public new SectionItem this[string response]
{
get { return (SectionItem)BaseGet(response); }
set
{
if (BaseGet(response) != null)
{
BaseRemoveAt(BaseIndexOf(BaseGet(response)));
}
BaseAdd(value);
}
}
protected override ConfigurationElement CreateNewElement()
{
return new SectionItem();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((SectionItem)element).Key;
}
}
And the SectionItem class:
public class SectionItem : ConfigurationElement
{
[ConfigurationProperty("key", IsRequired = true, IsKey = true)]
public string Key
{
get { return this["key"] as string; }
}
}
If I add a configuration property of type SectionItems in the Sections class that won't work for me, because I want to have multiple SectonItems inside the Section tag in the config file. I've searched for solutions but everything I've found didn't do the trick with this.
For a better understanding of what I'm trying to achieve this is how my config looks:
<configuration>
<configSections>
<section name="AdminConfig" type="XmlTest.AdminConfig, XmlTest"/>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<AdminConfig>
<Field name="field1" key="12345" path="asd"/>
<Section>
<Item key="12345"/>
<Item key="54321"/>
</Section>
</AdminConfig>
</configuration>
OK so I've found the problem. Although the Sections class had this [ConfigurationCollection(typeof(SectionItem), AddItemName = "Item", CollectionType = ConfigurationElementCollectionType.BasicMap)] I had to annotate the property in the ConfigurationSection class, as follows:
[ConfigurationProperty("Section")]
[ConfigurationCollection(typeof(Sections), AddItemName = "Item")]
public Sections Sections
{
get
{
return (Sections)this["Section"];
}
}
Now the items are recognized and stuff is working properly.