Використання ConfigurationManager для завантаження конфігурації з довільного місця


124

Я розробляю компонент доступу до даних, який буде використовуватися на веб-сайті, який містить поєднання класичних сторінок ASP і ASP.NET, і мені потрібен хороший спосіб керування його налаштуваннями.

Я хотів би скористатися користувачем ConfigurationSection, і для сторінок ASP.NET це чудово працює. Але коли компонент викликається через COM interop з класичної сторінки ASP, компонент не працює в контексті запиту ASP.NET і, отже, не знає web.config.

Чи є спосіб сказати, ConfigurationManagerщоб просто завантажити конфігурацію з довільного шляху (наприклад, ..\web.configякщо моя збірка знаходиться в /binпапці)? Якщо є, то я думаю, що мій компонент може повернутися до цього, якщо за замовчуванням ConfigurationManager.GetSectionповернеться nullдля мого спеціального розділу.

Будь-які інші підходи до цього були б раді!


Відповіді:


124

Спробуйте це:

System.Configuration.ConfigurationFileMap fileMap = new ConfigurationFileMap(strConfigPath); //Path to your config file
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedMachineConfiguration(fileMap);

Як я можу отримати програмно значення strConfigPath для мого додатка ASP.NET WebForms, розміщеного в sub.domain.com/virtualDir2 та шляху C: \ Portals \ App1 \ v2 та конфігураційного файлу в C: \ Portals \ App1 \ v2 \ web.config ?
Кікенет

1
@Kiquenet: Суть питання в тому, що strConfigPath - це довільне розташування. Іншими словами, ви вирішуєте, який шлях, замість того, щоб покластись на рамку, щоб спробувати завантажити конфігураційний файл зі свого звичайного місця. Я припускаю, що Server.MapPath надасть вам абсолютне розташування для будь-яких файлів у вашому рішенні.
Ізмаїл

1
Можливоvar config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~/web.config");
Kiquenet

@Kiquenet Однозначно.
Учо

66

Ще одне рішення полягає в тому, щоб замінити шлях файлу конфігурації середовища за замовчуванням.

Я вважаю це найкращим рішенням для завантаження файлу конфігурації нетривіального шляху, зокрема найкращий спосіб приєднати файл конфігурації до dll.

AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", <Full_Path_To_The_Configuration_File>);

Приклад:

AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", @"C:\Shared\app.config");

Більше інформації можна знайти на цьому блозі .

Крім того, в цій іншій відповіді є відмінне рішення, в комплекті з кодом для оновлення конфігурації програми та IDisposableоб'єктом для повернення його до початкового стану. За допомогою цього рішення ви можете зберігати тимчасовий конфігурацію програми:

using(AppConfig.Change(tempFileName))
{
    // tempFileName is used for the app config during this context
}

1
Це також працює для завантаження файлів web.config. Я використовую його для завантаження web.config замість app.config для консольного додатка. ;)
Джеймс Вілкінс

1
Це (та інші відповіді тут) не працює для мене. Я додав код у program.cs - функція: Main (). Мій конфігурація містить перенаправлення версії збірки (див. Stackoverflow.com/questions/30165393/… ), але перенаправлення не впливає на зміну конфігурації вручну.
Vortex852456

1
Ви використовували "APP_CONFIG_FILE"?
Saturn Technologies

40

Відповідь Ізмаїла, як правило, працює, проте я знайшов одне питання, а саме те, що використання, OpenMappedMachineConfigurationздається, втрачає успадковані групи розділів від machine.config. Це означає, що ви можете отримати доступ до власних користувацьких розділів (що є всіма бажаними ОП), але не до звичайних розділів системи. Наприклад, цей код не працює:

ConfigurationFileMap fileMap = new ConfigurationFileMap(strConfigPath);
Configuration configuration = ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
MailSettingsSectionGroup thisMail = configuration.GetSectionGroup("system.net/mailSettings") as MailSettingsSectionGroup;  // returns null

В основному, якщо поставити годинник на configuration.SectionGroups, ви побачите, що system.net не зареєстрований як SectionGroup, тому він майже недоступний через звичайні канали.

Я знайшов два способи обійти це. Перше, що мені не подобається, - це повторно реалізувати групи системних розділів, скопіювавши їх з machine.config у свій власний web.config, наприклад

<sectionGroup name="system.net" type="System.Net.Configuration.NetSectionGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
  <sectionGroup name="mailSettings" type="System.Net.Configuration.MailSettingsSectionGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <section name="smtp" type="System.Net.Configuration.SmtpSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  </sectionGroup>
</sectionGroup>

Я не впевнений, що веб-додаток після цього запуститься правильно, але ви можете правильно отримати доступ до розділуГрупи.

Друге рішення - це замість того, щоб відкрити ваш web.config як конфігурацію EXE, яка, мабуть, ближче до призначеної функції:

ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap() { ExeConfigFilename = strConfigPath };
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
MailSettingsSectionGroup thisMail = configuration.GetSectionGroup("system.net/mailSettings") as MailSettingsSectionGroup;  // returns valid object!

Я смію сказати, що жоден з наведених тут відповідей, ні мій, ні Ізмаїл, не використовують ці функції так, як планували дизайнери .NET. Але, здається, це працює для мене.


1
Для цієї ж мети можна також використовувати перевантаження ConfigurationManager.OpenExeConfiguration (String). Дивіться: codeproject.com/KB/dotnet/mysteriesofconfiguration3.aspx#t2_1
Шнайдер

10

Крім відповіді Ізмаїла, метод OpenMappedMachineConfiguration()завжди поверне Configurationоб’єкт. Отже, щоб перевірити, чи він завантажений, ви повинні перевірити HasFileвластивість, де true означає, що він походить з файлу.


9

Прийнята відповідь неправильна !!

Він отримує таке виняток щодо доступу до властивості AppSettings:

Неможливо надати об’єкт типу 'System.Configuration.DefaultSection', щоб ввести 'System.Configuration.AppSettingsSection'.

Ось правильне рішення:

System.Configuration.ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = "YourFilePath";
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

1
так, це, безумовно, правильна відповідь! Дякуємо, що опублікували свою відповідь.
Фабіо

Я думаю, що System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration є ще правильнішим, але він не доступний для .NET Core, тому в такому випадку ця відповідь, здається, завершить роботу.
Risord

4

Я надав значення конфігурації для розміщеного слова .nET Compoent наступним чином.

Компонент бібліотеки класів .NET, який викликається / розміщується в MS Word. Щоб надати значення конфігурації моєму компоненту, я створив winword.exe.config у папці C: \ Program Files \ Microsoft Office \ OFFICE11. Ви повинні мати змогу читати конфігураційні значення, як Ви робите, у традиційному .NET.

string sMsg = System.Configuration.ConfigurationManager.AppSettings["WSURL"];

1

Для ASP.NET використовуйте WebConfigurationManager:

var config = WebConfigurationManager.OpenWebConfiguration("~/Sites/" + requestDomain + "/");
(..)
config.AppSettings.Settings["xxxx"].Value;

0

Використовувати обробку XML:

var appPath = AppDomain.CurrentDomain.BaseDirectory;
var configPath = Path.Combine(appPath, baseFileName);;
var root = XElement.Load(configPath);

// can call root.Elements(...)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.