.NET Config Files configSource outside the application directory folder

.NetConfiguration

.Net Problem Overview


I have two applications one a console application and the other an ASP.NET app. They both need to know the same appSettings and connectionStrings. So ideally I would like to use the configSource property of app.config/web.config files to point that to a central location. For example

<connectionStrings configSource="D:\connectionStrings.config"/>
<appSettings configSource="D:\appSettings.config"/>

That however fails with an error:

> The configSource attribute is invalid.: The configSource 'D:\appSettings.config' is invalid. It must refer to a file in the same directory or in a subdirectory as the configuration file.

Is there anyway to still use the configuration managers appSettings/connectionStrings and get the values from an external location?
I'm happy with having to add code to do it, but I don't want to have to replace the entire configuration manager system.

.Net Solutions


Solution 1 - .Net

Another solution is simply to add the configuration file in all your projects as a link instead of actually copying the file to your projects. Then set the "Build Action" of the file to "Content" and "Copy to Output Directory" to "Copy if newer" and when you compile the project you will have the file in the output directory.

To add the file as a link in the "Add Existing Item" dialog box, there is an Add button with a dropdown. Choose "Add as link" from the dropdown on the Add button to complete the process.

Solution 2 - .Net

Under appSettings you can use file= instead of configSource=

Solution 3 - .Net

It seems that's that is the way it is. configSource must be in the same folder or deeper.

You could, although I'm not sure you should, use an NTFS hardlink. [mad grin]

Solution 4 - .Net

Visual Studio 2015

If you are having this issue with Web.Config the accepted answer is correct but just to expand since this had me giving myself the face-palm:

When you add a .config file to your project using 'Add As Link' and then set the link's Copy property to 'Copy If Newer' or 'Copy Always', then the physical file will be copied to the /bin folder.

Thus, when you have a config section defined in Web.Config like this:

 <section name="mySpecialConfig" type="System.Configuration.AppSettingsSection" requirePermission="false" />

then you must define the related config element like this:

  <mySpecialConfig configSource="bin\MySpecialConfig.config">
  </mySpecialConfig>

such that the configSource points to the physical bin\MySpecialConfig.config file not to the link Also, note that the path is a relative physical path.

That may seem ridiculously obvious but if you haven't done this before the physical file is not yet in the \bin folder so it may not click right away.

Solution 5 - .Net

You can load configuration from an arbitrary location, but it won't be available via the static properties of ConfigurationManager:

Configuration myConfig = ConfigurationManager.OpenExeConfiguration(path)

(There is an overload that allows multuple files to be specified, to support default/user-roaming/user-local hierarchy.)

Losing the static properties means all the code needs to be aware of the different configuration.

Solution 6 - .Net

In the case of connection strings, it is indeed possible to point to a shared file. If the shared file is on a network UNC, it requires administrative privileges on the machine where the app will be hosted.

Solution: In your web.config, use configSource to point to a local config file. Due to .Net restrictions, this must be at or below the level of the root config file. I just point to a file in the app folder itself:

<connectionStrings configSource="ConnectionStrings.config" />

In a shared location that is accessible by the application pool user, add the config file containing shared connection strings. This file must not contain any xml other than the connectionStrings section itself. The shared file, ConnectionStrings.config, looks like this:

<connectionStrings>
    <clear/>
    <add name="connString1" connectionString="connString1 info goes here"/>
    <add name="connString2" connectionString="connString2 info goes here"/>
</connectionStrings>  

Now the trick. Create a Windows symbolic link in your app folder pointing to the external, shared config file. You will need admin privileges to do this:

mklink ConnectionStrings.config \\someServer\someShare\someFolder\ConnectionStrings.config

We have just outsmarted .Net. The Configuration system will use the configSource setting to find connection strings in a local file called ConnectionStrings.config. The symbolic link looks like a file to .Net, and the symbolic link resolves to the shared configuration file.

Caveats: Changes to the shared file do not automatically trigger an app restart in .Net. In the case of IIS, the web site or app pool will need to be restarted manually.

Due to the need for administrative privileges to create the symbolic link, this approach may not work for everybody. There are two related alternatives that may work if the shared file is on the same logical drive - hard links and junctions. See this discussion and this discussion for more information.

Solution 7 - .Net

You can place both settings in the machine.config and then they are available for all you applications on the server.

Solution 8 - .Net

The solution I found worked best was to put the "shared" config files in a central files and then use a pre-build event in Visual Studio to copy them to a relative folder of each project which needed it.

Solution 9 - .Net

I had quite a struggle with this issue, but I found a good solution for it here: [test run with external config][1]

(You can direct the test run to copy files and directories into the test run directory by editing the .testrunconfig file.)

Although why the unit test type project can get config settings from its own app.config, but not be able to load referenced config files like a normal app.config is kind of baffling to me. I'd call it a bug because you would expect a test project app.config to behave the same way that the application's app.config behaves, but it doesn't.

[1]: https://stackoverflow.com/questions/152866/how-can-you-use-external-configuration-files-i-e-with-configsource-with-an-m "test run with external config"

Solution 10 - .Net

You can use the file attribute rather than configSource

There's a good article here on it

This allows you to specify a relative path like so

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings file="..\..\..\..\..\..\ExternalFile.config"></appSettings>
</configuration>

The path is relative to the output directory.

Then in ExternalFile.config you just add the appSettings section

<appSettings>
    <add key="SomeKey" value="alue"/>
</appSettings>

Solution 11 - .Net

If you have multiple projects that need to share same connection string, put the connection string config file you want to share between different projects in the class library project. And then from the project that needs to use the connection string, do this:

  1. If it's a Console project or Unit Test project:

In Console or Unit Test projects, do this in app.config: <connectionStrings configSource="connectionString.config"/>

That's it.

Why there is no link needed at all? Answer: when you build the project, connectionString.config gets copied to the output folder. The other projects' app.config files also get copied to the output folder. So when you run the start up project, the app.config of the start up project IS in the same folder as connectionString.config. That's why there's no link needed.

  1. If it's a Web project:

In web config do this: <connectionStrings configSource="bin\connectionString.config"/>

Note that if you set connectionString.config file to Copy If Newer, sometimes Visual Studio 2019 doesn't detect the change. So you can just set it to Copy Always.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRobert MacLeanView Question on Stackoverflow
Solution 1 - .NetMunchoView Answer on Stackoverflow
Solution 2 - .Netuser223066View Answer on Stackoverflow
Solution 3 - .NetIain M NormanView Answer on Stackoverflow
Solution 4 - .NetSerexxView Answer on Stackoverflow
Solution 5 - .NetRichardView Answer on Stackoverflow
Solution 6 - .NetScottView Answer on Stackoverflow
Solution 7 - .NetfreggelView Answer on Stackoverflow
Solution 8 - .NetRobert MacLeanView Answer on Stackoverflow
Solution 9 - .Netmarcel_gView Answer on Stackoverflow
Solution 10 - .NetalexsView Answer on Stackoverflow
Solution 11 - .NetbobtView Answer on Stackoverflow