.NET 配置文件应用程序目录文件夹外的 configSource

我有两个应用程序,一个是控制台应用,另一个是 ASP.NET 应用程序。它们都需要知道相同的 appSettings 和 ConnectionString。因此,在理想情况下,我希望使用 app.config/web.config 文件的 configSource 属性将其指向中心位置。比如说

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

然而,这种做法以一个错误而失败:

ConfigSource 属性无效。它必须将同一目录或子目录中的文件引用为配置文件。

是否仍然可以使用配置管理器 appSettings/ConnectionStrings 并从外部位置获取值?
我很高兴不得不添加代码来完成这项工作,但我不希望必须替换整个配置管理器系统。

77005 次浏览

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

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.

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]

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.

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.

Under appSettings you can use file= instead of configSource=

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

(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.

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.

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.

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>

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.