Load custom configuration section from various locations - c#

Currently i'm facing an issue with a framework I'm developing.
I have a custom configuration section that handles data caching.
The configuration for this is stored in the web.config of the application as shown below.
<configSections>
<section name="CachingProviders"
type="Data.Caching.Providers.Configuration.CachingProviderConfigurationSection, Data.Caching" />
</configSections>
<!-- Start the DCF configuration here. -->
<CachingProviders>
<!-- Providers definition:
A provider is the object that make sure that the item can be stored in the cache or not.
-->
<Providers>
<Provider Name="SlidingCachingProvider" Time="5" IsDefault="False"
Type="Data.Caching.Providers.SlidingProvider, Data.Caching.Providers" />
<Provider Name="AbsoluteCachingProvider" Time="5" IsDefault="False"
Type="Data.Caching.Providers.AbsoluteProvider, Data.Caching.Providers" />
</Providers>
</CachingProviders>
Now, the code is working fine, I'm reading the configuration from the web.config
But now I want to know if there's an easy way to transform my code so that the configuration can be done in a seperate file in the bin directory, for example: data-caching.config
I know there is a solution that in the custom config section you define which file to load, but I want to keep my web.config as clean as possible, which means that I don't want to add a single thing if possible.

You can add a configSource attribute to your Providers node as:
<Providers configSource="providers.config"/>
See here and here. This should work for custom sections as well.

Related

Web.config IIS rewrite rule to ignore specific file

I have a site txt map sitemaphttp.txt on my site. I redirect all my traffic to HTTPS. I still want Google to be able to read this sitemap, so it won't read it from https://example.com/sitemaphttp.txt but from http://example.com/sitemaphttp.txt. What rewrite rule I need to add to web.config so it will ignore all the other rules and just let that specific file through.
To link to a custom site-map provider from a parent site map
From the parent site map, create a SiteMapNode in the location in
the navigation structure where you want the child site map to be
displayed.
For example, if you are using the default XmlSiteMapProvider class,
open the Web.sitemap file and add the following SiteMapNode in the
appropriate location in the hierarchy:
<siteMapNode provider="SimpleTextSiteMapProvider" />
Note
The provider attribute corresponds to the provider's name attribute in the Web.config file.
Add the custom site-map provider to the Web.config file by using an add element. The following code adds the custom provider named SimpleTextSiteMapProvider, but maintains XmlSiteMapProvider as the default site-map provider.
<configuration>
<!-- other configuration sections -->
<system.web>
<!-- other configuration sections -->
<siteMap defaultProvider="XmlSiteMapProvider">
<providers>
<add
name="SimpleTextSiteMapProvider"
type="Samples.AspNet.SimpleTextSiteMapProvider,Samples.AspNet"
siteMapFile = "siteMap.txt" />
</providers>
</siteMap>
</system.web>
</configuration>

Custom config elements collection in Web.config - Using a key to choose

Intro
I'm developing a WebApp built on C# ASP.NET.
I've been researching creating a "Custom Configuration" section with child elements in the Web.config file, and I've hit a bit of a snag when it comes to consuming the keys/values in the data.
I seem to be going round in circles and I don't know how to tackle the issue I'm having.
Situation
I have a few different Connection Strings defined in the Web.Config file, in the <connectionStrings> section. They are for dev, test, and live databases.
<connectionStrings>
<add name="connectionOne" connectionString="..." providerName="..." />
<add name="connectionTwo" connectionString="..." providerName="..." />
<add name="connectionThree" connectionString="..." providerName="..." />
</connectionStrings>
The WebApp is currently hard-coded to use one of these connection strings - if I need to change which one to use, I need to re-compile.
Desired Functionality
I'd like to define a section in the Web.config, let's say DbSettings.
In that, I'd then like to be able to define some child elements for, let's say DbSettings, in which I could define dbConnectionName, foo, bar etc. as attributes.
For example:
<dbSettings>
<dbSetting key="DbSetting1"
dbConnectionName="connectionOne"
foo="fooOne"
bar="barOne" />
... and so on
</dbSettings>
Then, perhaps in the <appSettings> section, define which of these DbSettings elements I want to use to get the settings from:
<appSettings>
<add name="dbSettingsKey" value="DbSetting1" />
</appSettings>
Desired Web.config section
Here is a fuller example of what I'd imagine my Web.config file to look like:
Connection Strings
<connectionStrings>
<add name="connectionOne" connectionString="..." providerName="..." />
<add name="connectionTwo" connectionString="..." providerName="..." />
<add name="connectionThree" connectionString="..." providerName="..." />
</connectionStrings>
App Settings
<add key="dbSettingsKey" value="DbSetting1" /> // or 2, or 3 etc.
DbSettings (custom section)
<dbSettings>
<dbSetting key="DbSetting1"
dbConnectionName="connectionOne"
foo="fooOne"
bar="barOne" />
<dbSetting key="DbSetting2"
dbConnectionName="connectionTwo"
foo="fooTwo"
bar="barTwo" />
<dbSetting key="DbSetting3"
dbConnectionName="connectionThree"
foo="fooThree"
bar="barThree" />
</dbSettings>
My question...
How the devil am I going to get this desired functionality in the C# code?
I've read loads on "creating your own custom section", and similarly "creating a custom config collection". But, I just can't seem to glue it all together to apply for my situation.
I'd like to be able to have a class (like the one I'm using at the moment with the hard-coded strings), which I can reference necessary properties (as I am doing, at the moment) - and then the code can dynamically load the correct settings at run-time from the sections I've described above.
As always, thank you in advance for your suggestions and help.
I agree with the comments. The way this is usually done is you deploy a different web.config to each environment. When your deployment group (or you) deploys, you deploy everything EXCEPT the web.config unless you have changes to push.
In answer to your other question, adding a custom section is not trivial. It's quite a bit of work. Custom section handler which requires a whole bunch of configuration element classes and a bunch of configuration element collection classes... and then, if you want it to "work" correctly, you also need to create a schema and register that with the IDE, etc.
For your particular case, I'd just do it the "normal" way :).

vs 2012 Web.Config transformation

I am trying to add a set of URL Rewriting rules but only to the published version of the web site I'm developing.
I find all sorts of examples if i want to change say the connection string value, but I cannot find an example of how to add something that does ot already exists in the main web.config.
What I need is to add the rewrite node under the system.WebServer.
All you need is to use xdt:Transform="Insert" attribute within a tag that you want added during transformation. Read more about it here: http://msdn.microsoft.com/en-us/library/dd465326.aspx
You can take the below sample as a starting point (which is my Web.Release.config file):
<?xml version="1.0"?>
<!-- For more information on using Web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<!-- Enable static content caching in release mode -->
<system.webServer xdt:Transform="Insert">
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="5.00:00:00" cacheControlCustom="public" />
</staticContent>
</system.webServer>
</configuration>

Variables in XML configuration

I'm trying to use xml configuration file in my project. Now it looks like:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="replication" type="Project.Replication.ReplicationConfigSection, Project.Replication" />
<section name="processing" type="Project.Processing.ProcessingConfigSection, Project.Processing" />
</configSections>
<replication>
<streams>
<stream name="STREAM_DATA_14360" />
</streams>
</replication>
<processing dataStream="STREAM_DATA_14360" />
</configuration>
It works OK, but I'm confused with duplicates in it ("STREAM_DATA_14360").
Can you remind me, how to create variables in XML or something for data reusing to be acceptable in application configuration?
UPDATE:
In real life my configuration has much more sections. There is a value, which apeears in many of this sections: STREAM_DATA_14360. So I want to be able to change this value only in one place of config file, and in other places to use reference to it.
Speed of changing configuration - is the first reason for it.
Size of a file is a second, because values can be huge: STREAM_INFO_FUTURE_SESSION_CONTENTS_12421 (that is third-party names)
You can simply add this value in <appSettings> and access it as you are saying.
You can do this as below:
<appSettings>
<add key="StreamName" value="STREAM_DATA_14360"/>
</appSettings>
In the code, you can access it as below:
string streamName = ConfigurationManager.AppSettings["StreamName"];
Make sure to add reference to System.Configuration assembly before using this.
XML doesn't have any native expansion macros or templating - any scenario would require that you do a preprocess step or have the code that reads the config involved in substituting the value.
If those aren't redacted names though, it seems a simple search/replace would solve the problem without much of a concern on false positives.
You could put something together with T4 templates as a preprocessor, whether that's worth it really depends on how often you expect to modify this file.
It should also be possible to shoehorn the web.config transformation engine into doing the replacements, but you may have to write some hosting code for the XDT engine depending on how your config file is setup.
Apart from using external code that might (or might not) facilitate your life, you can define your own classes that inherit from ConfigurationSection, wherein you define and encapsulate your key/value pairs and use the ConfigurationProperty attribute.
Have look at http://msdn.microsoft.com/en-us/library/2tw134k3.aspx for more info on How to: Create Custom Configuration Sections Using ConfigurationSection.
EDIT: you can make references in xsd (check here)
Thanks for your answers. I agree with Mark, there's no support of variables or references in XML. But, in my case there's much simpler solution. I feel stupid now, but hope that it will help another slowpoke too.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="global" type="Project.GlobalConfigSection, Project" />
<section name="replication" type="Project.Replication.ReplicationConfigSection, Project.Replication" />
<section name="processing" type="Project.Processing.ProcessingConfigSection, Project.Processing" />
</configSections>
<global>
<streamNames>
<streamName name="STREAM_DATA_14360" id="1"/>
</streamNames>
</global>
<replication>
<streams>
<stream nameId="1" />
</streams>
</replication>
<processing dataStreamId="1" />
</configuration>
Consequence: need to edit code to use global section as a source of all long names
Advantage: fast renaming, reusability of values

Edit App.Config name-value pairs from a separate tool

I am trying to create a simple tool for a service person to update a few entries in the App.Config of a different program. The App.Config file contains custom parameters used upon initialization of our program.
Since the App.Config contains many sensitive items a tool is needed to ensure only certain parameters are changed. Thus, the reason not to allow them to edit the App.Config directly.
My questions:
How can I access the name-value pairs from the config sections of an App.config from a separate program?
Which is better suited for the UI: Winforms or WPF? Are their controls that make it easy to add more entries in the future?
The tool should allow the user to set either a String, int, double or Boolean.
Here is the structure of the App.Config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="Settings">
<section name="Section1" type="System.Configuration.NameValueSectionHandler"/>
<section name="Section2" type="System.Configuration.NameValueSectionHandler"/>
<section name="Section3" type="System.Configuration.NameValueSectionHandler"/>
<section name="Section4" type="System.Configuration.NameValueSectionHandler"/>
</sectionGroup>
</configSections>
<Settings>
<Section1>
<add key="NAME_STRING" value="Some String"/>
</Section1>
<Section2>
<add key="NAME_INTEGER" value="10"/>
</Section2>
<Section3>
<add key="NAME_DOUBLE" value="10.5"/>
</Section3>
<Section4>
<add key="NAME_BOOLEAN" value="true"/>
</Section4>
</Settings>
... Omitted ...
</configuration>
In the program which uses the App.Config itself, I can easily change the values like so:
NameValueCollection nvc = (NameValueCollection)ConfigurationManager.GetSection("Settings/Section1");
Is there a similar way to do this from a separate program after loading the App.Config?
An answer to Question 1: An app.config file is an XML file. It might be easiest to load it as an XML document and modify that programmatically, followed by a save, than to use System.Configuration classes.
ETA: I believe it can be done with ConfigurationManager. Look at the OpenMappedExeConfiguration method. There's a good example there.
You could treat the app.config file as a normal XML file. Use either XDocument or XmlDocument to load the file.
Then use XPath or Linq to XML to find the name-value pairs.
As for Windows.Forms vs. WPF, its a design decision. Both have good and bad points.
[Update]
If you still want to use System.Configuration, you can use the ConfigurationManager.OpenExeConfiguration to get access to the other program's app.config file. This returns a Configuration object, which has a GetSection method.

Categories