Providing intellisense/xsd validation to configsections - c#

in a small c# project, I'm trying to create a simple custom configsection.
I followed the instructions in CodeProject: Unraveling the Mysteries of .NET 2.0 Configuration and everything work nicely... apart from the fact that I don't get xsd validation and intellisense on the config.
My config is shown below.
<configuration>
<configSections>
<section name="pizza" type="TestConfig.Configuration.PizzaConfigurationSection, TestConfig.Configuration"/>
</configSections>
<pizza name="Margherita" timeToCook="00:10:00" price="15.12">
<cook firstName="Nicola" lastName="Carrer" rank="7" />
<toppings>
<add name="Mozzarella" percentage="0.6" />
<add name="Tomato sauce" percentage="0.28" />
<add name="Oregano" percentage="0.02" />
<add name="Mushrooms" percentage="0.1" />
</toppings>
</pizza>
</configuration>
On this article (XSDExtractor) I found a tool that creates an xsd file for the configsection. It works fine, i.e. it provides intellisense and validation, for the main attributes (e.g. "price") and the single elements ("cook"). However I could not make it work for the collections (the "toppings").
My questions:
Is there any other tool that provides xsd generation of ConfigurationSection classes?
Has someone run XSDExtractor successfully on a ConfigurationSection with a collection property?
Thanks a lot,
Nicola

I haven't used XSDExtractor but one tool which I strongly recommend is Configuration Section Designer. It's a Visual Studio add-in that allows you to graphically design .NET Configuration Sections and automatically generates all the required code and a schema definition (XSD) for them.

Related

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"/>

Can I make a monoSettings section in a web.config file optional to run on Windows as well as under Mono?

I have had to add a monoSettings section to my Web.config file as I need to support colons in the url (similar to this question: ASP.NET special characters in URL (colon) not working even with requestPathInvalidCharacters="").
Now when I run my web-api service in visual studio (which I do for ad-hoc testing) it gives an error:
"The configuration section 'monoSettings' cannot be read because it is missing a section declaration"
I'm just wondering what is the best way to support this config in my Mono service without impacting being able to run in on Windows? Can I just flag it as optional or unimportant so that it won't fail when trying to read the config? Or is it just better to have a different build configuration for Mono - but I'd then have to maintain two versions of web.config with just this one minor difference.
I resolved this issue by adding a configSection to my Web.config as follows:
<configuration>
<configSections>
<sectionGroup name="system.web">
<section name="monoSettings" type="DataSetSectionHandler,SectionHandlers" />
</sectionGroup>
</configSections>
<system.web>
<monoSettings verificationCompatibility="1" />
<httpRuntime requestPathInvalidCharacters="<,>,*,%,&,\,?" />
</system.web>
</configuration>

How to programatically update custom attribute in app config file

My app.config.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
</configSections>
<Something SettingsLocation="D:\test\test\file.json" />
<Something />
</configuration>
I need to update SettingsLocation programatically.
I found this some answers, but it is not clear to me.
Thanks fo help.
Each application has it’s own configuration file, be it a windows based application or web based.
This application configuration file defines information which can be used by application to make decisions, to load some other information or may contain the custom configuration which can be empowered to do anything.
There can also be scenarios where an application may want to change\modify the existing setting in the application configuration file and those changes should not only take effect immediately but should also be persisted.
Possible solution is already shown here

How to manage configuration from several class libraries in .NET?

I'm looking for a best practice for managing configuration on a project with multiple class libraries. I'm looking for maintainability and ease of implementation.
Let's assume a simple example: A console project with 2 class libraries. Each class library need their own configuration settings, and there are some settings that are common to several.
Class Library 1
CL1Setting
GlobalSetting
Class Library 2
CL2Setting
GlobalSetting
A first approach would be to create all the necessary settings on the main project:
GlobalSetting
CL1Setting
CL2Setting
But this present several problems:
It can get cluttered fast if there are lots of settings.
It is not easy to maintain: How to know which settings are needed for each library?
It can create naming conflicts. What if CL1Setting and CL2Setting would have the same name?
An ideal solution for me (although I'm afraid not possible) would be having custom library settings in separate files, or at least different sections. Something like this:
<configuration>
<appSettings>
<add key="globalSetting" value="cl1Global"/>
</appSettings>
<appSettings file="CL1.config" >
<add key="cl1setting" value="cl1setting1"/>
</appSettings>
<appSettings file="CL2.config">
<add key="cl2setting" value="cl2setting2"/>
</appSettings>
</configuration>
Any suggestions?
EDIT
As Ken Henderson suggests, config sections are another approach. However, although with their own advantages, they require coding, so I don't find it ideal though. (This will probably end up being the best option though)
EDIT 2
joseph.ferris suggestion to look at Configuration Section Designer on CodePlex (csd.codeplex.com) was good. I found further problems, reported here (in case some is interested) http://csd.codeplex.com/discussions/278354
I think what you are looking for is a custom configuration section instead of appSettings. This is commonly used by 3rd party libraries (log4net is the first that comes to mind) to provide a way to configure their settings via your app/web config file. Note that this also provides the basis for how MS creates their configuration sections.
I've successfully used this in several different projects including one that included the ability to add new implementations of algorithms to an analysis program.
You could use your own naming convention to reduce the risk of appSettings naming collisions. And/or create custom configuration sections.
<configuration>
<appSettings>
<add key="Shared.Setting1" value="..."/>
<add key="CL1.setting1" value="..."/>
<add key="CL1.setting2" value="..."/>
<add key="CL2.setting1" value="..."/>
<add key="CL2.setting2" value="..."/>
</appSettings>
</configuration>
I'm not sure an administrator would need to know which setting belongs to which library, but a naming convention helps promote a logical grouping - I would use prefixes that are meaningful to an administrator, rather than say a class library name - e.g. "Logging." for appSettings related to logging.
Microsoft uses colon as a delimiter for namespace in some of their code.
Example their Azure samples. Here they use ida: as prefix.
ConfigurationManager.AppSettings["ida:ClientId"];
In Microsoft ASP.NET in the Web.config file you can see:
<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>

Does Monodevelop support configuration files?

I added a file app.config to a C# mono project.
Inside the project I used
foreach (string key in ConfigurationManager.AppSettings)
{
string value = ConfigurationManager.AppSettings[key];
Console.WriteLine("Key: {0}, Value: {1}", key, value);
}
The config file looks like this
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="Key1" value="Kevin" />
<add key="Key2" value="150" />
<add key="Key3" value="Rice" />
</appSettings>
</configuration>
No keys are detected. How can I read the config values?
This answer comes awfully late, but for anybody that comes across this, yes, mono does support configuration files. You can use the ConfigurationManager method discussed above or you can even create your own custom settings section in the app.config file and manipulate it through a class which derives from ApplicationSettingsBase. In my opinion, this is a much more natural way of handling the app.config file because you work with a class and strongly typed properties, rather than accessing strings out of an array with the way that ConfigurationManager does it. Creating a class for app settings is pretty easy, too. Here's the MSDN page explaining how to create the class: http://msdn.microsoft.com/en-us/library/system.configuration.applicationsettingsbase.aspx
The only caveat to be aware of with Mono is that the .NET Framework allows UserScopedSettings to be defined in the app.config file (to provide a default value) but Mono will throw exceptions if you do that. The workaround for that is to leave UserScopedSettings out of the app.config file and just define the default value for a property in code. This isn't a perfect workaround because it doesn't give a way to change the default value outside of the code, but this will be sufficient in most cases.

Categories