Allowing Class Library to use App.config from UI Project - c#

I recently decoupled my UI layer from my Models and Service layer by splitting them into separate projects. Now I get the following error upon compiling my solution:
System.Configuration.ConfigurationErrorsException: 'An error occurred creating the configuration section handler
for IOLegend: Could not load file or assembly 'Laborare.Core' or one of its dependencies.
The system cannot find the file specified.'
In my class library, I use ConfigurationManager to read application configuration settings such as:
var IoLegendConfig = (IOLegendConfig)ConfigurationManager.GetSection("IOLegend");
var Rs232Config = (RS232ConnectionConfig)ConfigurationManager.GetSection("RS232Connection");
public static string _Metric_Setting = ConfigurationManager.AppSettings["metric_setting"];
Here is my configSections in the app.config:
<configSections>
<section name="TCPConnection"
type="Laborare.Core.Configuration.TCPConnectionConfig, Laborare.Core"/>
<section name="RS232Connection"
type="Laborare.Core.Configuration.RS232ConnectionConfig, Laborare.Core"/>
<section name="IOLegend"
type="Laborare.Core.Configuration.IOLegendConfig, Laborare.Core" />
</configSections>
The app.config is located in my UI project. What is the problem here? Am I not correctly directing the ConfigurationManager in my class library? I seem to be using the correct namespaces. Any help would be greatly appreciated.
Here is a picture of my current solution structure.

Related

No connection string could be found in the App.config file

Visual Studio Solution:
(Project 1) I have a ASP .NET Framework API project that uses Entity Framework to access to Database.
(Project 2) Now I created NUnit project that is calling methods of project 1. Some of project1's methods are calling EF methods, so:
I added nuget package of Entity framework to project 2
I created an App.config file in project 2
But after executing test methods I get:
Test method Test.SchedulerTesting.TestMethod5 threw exception:
System.InvalidOperationException: No connection string named
'MyEntities1' could be found in the application config
file.
My app.config (project 2) content:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- 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" />
</configSections>
<connectionStrings>
<add name="MyEntities1" connectionString="provider=System.Data.SqlClient;provider connection string="data source=**********;initial catalog=******;user id=sa;password=**********;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
</configuration>
My Model.Context.cs (project 1) first lines:
public partial class MyEntities1: DbContext
{
public MyEntities1()
: base("name=MyEntities1")
{
}
//...
}
An app.config file applies when your production application is running. When running tests under a test runner, you need to set up a config for use with your tests. It will usually contain the same stuff as your production config.
In your case, you need a config file named something like project2.dll.config in order for the configuration to be made available to your tests. Visual Studio will not automatically rename an App.config for you because it doesn't know you want to use NUnit.
Funny thing, the first blog post I ever wrote (2005) talks about this and has many more details: http://charliepoole.org/technical/how-nunit-finds-config-files.html

Mock Umbraco configuration in test project

When running unit tests on code using some Umbraco Core extensions, such as string.ToUrlSegement(), the following error is thrown:
System.Configuration.ConfigurationErrorsException: Could not load the Umbraco.Core.Configuration.UmbracoSettings.IUmbracoSettingsSection from config file, ensure the web.config and umbracoSettings.config files are formatted correctly
How do you prevent this happening?
Beside copying all Umbraco settings into your test projects app.config, you can add the following configuration:
<configSections>
<sectionGroup name="umbracoConfiguration">
<section name="settings" type="Umbraco.Core.Configuration.UmbracoSettings.UmbracoSettingsSection, Umbraco.Core" requirePermission="false" />
</sectionGroup>
</configSections>
This prevents that exception being thrown when using Umbraco core functions dependent on configuration of a main project.
Discovered this and some other great tips here.

Use App.config with a Custom Section shared between two different projects

Scenario
I have developed a windows service which is configured by its App.config file.
This file contains the information in the standard sections (connectionStrings, appSettings) and in a custom section (sourceTabSection).
In the windows service project i have 4 classes which allow me to get/set the config file content. They are based on what is written in this article: Writing a Custom ConfigurationSection to handle a Collection and i have no problems on using them inside my service.
The problems come when i try to get/set the custom section (with the standard sections i don't have any problems) of the App.config, belong to the Windows service, using another application that in my case is a Windows Form that allows users to view/set parameters for the windows service.
The Windows Form application has the same pack of 4 classes used by the service, in order to handle the App.config.
When the code that get/set custom parameters of Windows Service is excuted on the Windows Form app I get the following error message:
{"An error occurred creating the configuration section handler for sourceTabSection: Could not load type 'DataReportingService.CustomSourceTabSection.SourceTabSection' from assembly 'DataReportingService'."}
The problem is due to this following line of code in the App.config
<section name="sourceTabSection" type="DataReportingService.CustomSourceTabSection.SourceTabSection, DataReportingService"/>
The attribute type of the tag shown above has the following meaning (it's explained here: section Element for configSections):
type="Fully qualified class name, assembly file name, version, culture, public key token"
Following what is written on Writing a Custom ConfigurationSection to handle a Collection article I defined only the first two parameter (Fully qualified class name, assembly file name) of the attribute type. Microsoft documentation (no more maintained) doesn't specify that the other parameters can be not defined, but the example that I followed and others use this approach.
However the point is this phrase about the type attribute on Microsoft documentation:
The assembly file must be located in the same application directory
So, due to this bond, seems to be impossible to handle custom section of an application A from another application B (which has another assembly) using this approach.
So do you know how could I solve this problem?
Windows service - App.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="sourceTabSection" type="DataReportingService.CustomSourceTabSection.SourceTabSection, DataReportingService"/>
</configSections>
<!-- *** CUSTOM SECTION *** -->
<sourceTabSection>
<Tables>
<sourceTab name="TEST" db_conn_str="****"
keep_time="1" scan_frequency_process_rows="1"
scan_frequency_delete_processed_rows="1" />
<sourceTab name="TEST_2" db_conn_str="****"
keep_time="1" scan_frequency_process_rows="1"
scan_frequency_delete_processed_rows="1" />
</Tables>
</sourceTabSection>
<!-- *** STANDARD SECTIONS *** -->
<connectionStrings>
<add name="DB_Target" connectionString="Data Source=192.168.2.2;Initial Catalog=PlantDompe;Persist Security Info=True;User ID=sa;Password=Gf6swML0MXiqbOFuvRDvdg==;"
providerName="System.Data.SqlClient" />
</connectionStrings>
<appSettings>
<add key="TAB_ALARMS_TARGET" value="AlarmsProcess" />
<add key="TAB_VALUE_TARGET" value="USER_CHANGES" />
<add key="TAB_LOGINS_TARGET" value="USER_LOGONS" />
<add key="LOG_DIR" value="C:/Users/rossi/Documents/Visual Studio 2017/Projects/DRS_proj/Log/" />
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
<system.web>
<trust level="Full" />
<webControls clientScriptsLocation="/aspnet_client/{0}/{1}/" />
</system.web>
</configuration>
Ugly solution
If found a work around to this problem by performing the two following steps on the Windows Form application that need to view/set the parameters (custom and no custom) inside the App.config of the Windows Service:
Using visual studio i go to Solution Properties > Application tab, and I change the following values
Assembly name = DataReportingService
Default namespace = DataReportingService
Note: DataReportingService is the name of the window service with the App.config file
Find and replace all the references to old namespace with the new one
In this way I can handle the custom section of the App.config, but honestly it's a really ugly solution and I think that there should be something better.
Thanks #Alex Paven, your comment has helped me to solve this problem!
Here below there are the detailed steps of what I've done:
I moved the 4 classes which handles the Windows service config file in a Class Library project (.NET Framework) called: DRS_CustomConfig.
I changed the namespace of the 4 classes with the following value: DRS_CustomConfig and then I compiled the project.
I linked the external library both in the Windows service project and in Windows Form application
For each class of both projects which need to use the classes contained in the external library I inserted the following piece of code:
using DRS_CustomConfig;
In the App.config of the Windows service I changed the section element as follows:
Old
<section name="sourceTabSection"
type="DataReportingService.CustomSourceTabSection.SourceTabSection,
DataReportingService"/>
New
<section name="sourceTabSection"
type="DRS_CustomConfig.SourceTabSection, DRS_CustomConfig"/>

How to change configSections, section, type element? Specifically Version

I'm posting my question here and to CodeProject, as a question to the famous article series on the mysteries of config files.
From the article:
Optionally, you may specify culture, version and public key (for
signed assemblies) values if you wish to ensure only a specific
version of an assembly is searched for when your .config file is
parsed.
I'm using the following code to open and initialize the config file:
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = path;
config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
section = (OptionsSection)config.GetSection("myoptionsdata");
if (section == null)
{
section = new OptionsSection(0, "aaaa", "bbbb", "cccc",14);
config.Sections.Add("myoptionsdata", section);
config.Save(ConfigurationSaveMode.Full);
}
That creates the following:
<configSections>
<section name="myoptionsdata" type="my.namespace.OptionsSection, myAssembly,
Version=1.0.3.0, Culture=neutral, PublicKeyToken=111222aaaabbb"
allowLocation="true" allowDefinition="Everywhere"
allowExeDefinition="MachineToApplication" overrideModeDefault="Allow"
restartOnExternalChanges="true" requirePermission="true" />
</configSections>
Notice how the 'type' has Version, Culture, and the PublicKeyToken. I need to eliminate these, or at least the Version. The problem is that I deploy the app with a specific version, then I bump the version and issue updates. But when the read is done on the config it fails because the version is explicit.
So really all I want is this:
<configSections>
<section name="myoptionsdata" type="my.namespace.OptionsSection, myAssembly" />
</configSections>
I have never once seen an example that includes the extended type values. Every example shows Save() creating type="namespace.class,assembly", and yet that doesn't seem to be the default behavior.
So, with reference to the above quote, where can I find information on managing those "optional" values?
For anyone googling, this is one of the causes of the infamous error below:
Exception: An error occurred creating the configuration section
handler for myoptionsdata: Could not load file or assembly
'myAssembly, Version=1.0.3.0, Culture=neutral,
PublicKeyToken=111222aaaabbb' or one of its dependencies. The located
assembly's manifest definition does not match the assembly reference.
(Exception from HRESULT: 0x80131040)
(C:\Users\me\AppData\Roaming\product\dir\name.config line 4)
I believe my question is similar to this one which so far has not received any response.
Going "off the menu", I just want to deploy a config file to a specific location (non-default) and allow users to set options in a Tools>Options sort of form. Most apps do this. Is there any easy and commonly accepted way of doing this? I should note that my app is an Outlook Addin, and I do my config file like this because I want to store addin settings in an addin-specific config file rather than anywhere near Outlook configs.
The assembly that contains your custom configuration section has a strong name. Strong-naming an assembly explicitly prevents the kind of in-place version upgrade you want to do. Remove the strong name from that assembly and the assembly loader will stop caring what version it is.

Configuration system failed to initialize in log4net

I am getting this exception "Configuration system failed to initialize" while reading connection string from app_config in window application
string con = ConfigurationSettings.AppSettings["ConnectionString"].ToString();
on this line after entering following lines
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
in AssemblyInfo.cs. if i remove this line from Assemblyinfo.cs then there is no exception i am adding this assembly for logging purpose
I am not sure but if you are using VSTO for MS Office Add-In Development than below post might help you.
Why is log4net not recognized in configuration file?
You need to add log4net also in the section block
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
</configSections>
This is a .NET problem, not a log4net problem. Your app.config file isn't being loaded. See Configuration System Failed to Initialize for a good answer to the real problem.

Categories