Как изменить appSettings web.config во время выполнения?

84

Я не понимаю, как изменить значения web.config appSettings во время выполнения. Например, у меня есть этот раздел appSettings:

<appSettings>
  <add key="productspagedesc" value="TODO: Edit this default message" />
  <add key="servicespagedesc" value="TODO: Edit this default message" />
  <add key="contactspagedesc" value="TODO: Edit this default message" />
  <add key="aboutpagedesc" value="TODO: Edit this default message" />
  <add key="homepagedesc" value="TODO: Edit this default message" />
 </appSettings>

Скажем, я хочу изменить ключ "homepagedesc" во время выполнения. Я пробовал статические классы ConfigurationManager и WebConfigurationManager, но настройки доступны только для чтения. Как изменить значения appSettings во время выполнения?

ОБНОВЛЕНИЕ: Хорошо, вот я 5 лет спустя. Я хотел бы отметить, что опыт подсказал мне, что мы не должны помещать какую-либо конфигурацию, которая преднамеренно редактируется во время выполнения, в файле web.config, а вместо этого мы должны поместить ее в отдельный файл XML, как то, что один из пользователей прокомментировал ниже. Это не потребует редактирования файла web.config для перезапуска приложения, что приведет к тому, что вам будут звонить рассерженные пользователи.

jerbersoft
источник
Вот хорошая ссылка, которая хорошо объясняет изменение web.config во время выполнения и его влияние на приложение. http://aspdotnethacker.blogspot.com/2010/05/modify-webconfig-file-at-runtime.html
5
@ user330004, предоставленная вами ссылка больше не действительна
МакАрти,
Поиск архивной версии займет всего несколько секунд !
Стюарт

Ответы:

84

Вам нужно использовать WebConfigurationManager.OpenWebConfiguration(): Например:

Dim myConfiguration As Configuration = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~")
myConfiguration.ConnectionStrings.ConnectionStrings("myDatabaseName").ConnectionString = txtConnectionString.Text
myConfiguration.AppSettings.Settings.Item("myKey").Value = txtmyKey.Text
myConfiguration.Save()

Я думаю, вам также может потребоваться установить AllowLocation в machine.config. Это логическое значение, указывающее, можно ли настроить отдельные страницы с помощью элемента. Если "allowLocation" имеет значение false, его нельзя настроить в отдельных элементах.

Наконец, имеет значение, если вы запускаете свое приложение в IIS и запускаете тестовый образец из Visual Studio. Идентификатором процесса ASP.NET является учетная запись IIS, ASPNET или СЕТЕВЫЕ СЛУЖБЫ (в зависимости от версии IIS).

Возможно, потребуется предоставить ASPNET или СЕТЕВЫЕ СЛУЖБЫ. Изменить доступ к папке, в которой находится web.config.

Митч Уит
источник
1
Спасибо за ответ, Митч. Вы ответили на мой вопрос. Я запустил VS 2008 как администратор, и все было в порядке.
jerbersoft 06
Возможно, очевидно для других (не для меня), этот ответ, а также ответ Амина, который функционально одинаков, фактически перезаписывает ваш физический файл web.config, а не просто отменяет настройку в памяти для конкретного запущенного экземпляра.
k3davis
24

Изменение web.config обычно вызывает перезапуск приложения.

Если вам действительно нужно, чтобы ваше приложение редактировало собственные настройки, вам следует рассмотреть другой подход, такой как создание базы данных настроек или создание XML-файла с редактируемыми настройками.

Джоэл
источник
1
Привет, спасибо за ответ. Но есть класс «Конфигурация», у которого есть функция «Сохранить». Вам действительно нужно перезапускать приложение, чтобы новые настройки вступили в силу?
jerbersoft 06
4
Изменение web.config автоматически запускает перезапуск приложения.
Майк Коул,
1
Не рекомендуется динамическое изменение web.config. Я бы предпочел сохранить значение в файле (xml).
Дипак Мишра
может кто-нибудь объяснить, почему перезапуск приложения - это плохо, и многие рекомендуют переместить атрибут в другой файл?
Бен
1
@Ben - Я знаю, что прошло несколько месяцев, но на всякий случай - перезапуск приложения будет означать, что любой, кто вошел в ваше приложение в момент перезапуска, автоматически выйдет из системы и, скорее всего, столкнется с ошибкой. (несмотря на различные сценарии, такие как веб-фермы ...). сердитые пользователи обращаются в
службу
24

А если вы хотите избежать перезапуска приложения, вы можете убрать appSettingsраздел:

<appSettings configSource="Config\appSettings.config"/>

в отдельный файл. И в сочетании сConfigurationSaveMode.Minimal

var config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~");
config.Save(ConfigurationSaveMode.Minimal);

вы можете продолжать использовать этот appSettingsраздел в качестве хранилища для различных настроек, не вызывая перезапуска приложения и без необходимости использовать файл с форматом, отличным от обычного раздела appSettings.

Чиприан Тейосану
источник
22

2012 Это лучшее решение для этого сценария (протестировано с Visual Studio 2008 ):

Configuration config = WebConfigurationManager.OpenWebConfiguration(HttpContext.Current.Request.ApplicationPath);
config.AppSettings.Settings.Remove("MyVariable");
config.AppSettings.Settings.Add("MyVariable", "MyValue");
config.Save();

Обновление 2018 =>
Протестировано в 2015 году - Asp.net MVC5

var config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~");
config.AppSettings.Settings["MyVariable"].Value = "MyValue";
config.Save();

если вам нужно проверить наличие элемента, используйте этот код:

var config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~");
if (config.AppSettings.Settings["MyVariable"] != null)
{
config.AppSettings.Settings["MyVariable"].Value = "MyValue";
}
else { config.AppSettings.Settings.Add("MyVariable", "MyValue"); }
config.Save();
Амин Гадери
источник
Не могли бы вы пояснить, почему так лучше? Я знаю, что с configSection иногда бывает немного сложно.
julealgon
1
Этот код меньше и понятнее! По крайней мере для меня.
Amin Ghaderi
3
О, тогда это из-за личного вкуса, я вообще-то думал, что это как-то логически иначе. Я категорически не согласен с вами в этом случае, хотя на самом деле по ряду причин: во-первых, потому что вам нужно указать один и тот же ключ дважды, во-вторых, потому что то, что вы делаете, семантически отличается от того, что действительно необходимо ('update' vs 'remove-> add ') и в-третьих, потому что код на самом деле длиннее (не уверен, почему вы здесь думаете иначе) и допускает ошибки. Кроме того, что, если по какой-то причине ваш код дает сбой между вызовами? Я думаю, что ваше приложение оттуда не работает.
julealgon 01
2
Этот код удаляет все комментарии, относящиеся к MyVariable.
Blagus 08
Да, точно ! В этом коде можно переписать все переменные, но он работает. но я не рекомендую использовать его, когда вы использовали код комментария. Спасибо.
Амин Гадери
14

Я знаю, что это старый вопрос, но я хотел опубликовать ответ, основанный на текущем состоянии дел в мире ASP.NET \ IIS в сочетании с моим реальным опытом.

Недавно я возглавил проект в своей компании, в котором я хотел объединить и управлять всеми настройками appSettings и connectionStrings в наших файлах web.config в одном центральном месте. Я хотел реализовать подход, при котором наши настройки конфигурации хранились в ZooKeeper из-за зрелости и стабильности этого проекта. Не говоря уже о том факте, что ZooKeeper является приложением для управления конфигурацией и кластером.

Цели проекта были очень простыми;

  1. заставить ASP.NET общаться с ZooKeeper
  2. в Global.asax, Application_Start - получить настройки web.config из ZooKeeper.

Пройдя техническую часть, как заставить ASP.NET разговаривать с ZooKeeper, я быстро нашел и столкнулся со следующим кодом;

ConfigurationManager.AppSettings.Add(key_name, data_value)

Это утверждение имело наиболее логичный смысл, поскольку я хотел ДОБАВИТЬ новые настройки в коллекцию appSettings. Однако, как упоминалось в оригинальном плакате (и многих других), этот кодовый вызов возвращает ошибку, в которой говорится, что коллекция доступна только для чтения.

Проведя небольшое исследование и увидев все безумные способы решения этой проблемы, я был очень разочарован. Вместо того, чтобы отказываться или соглашаться на то, что казалось менее чем идеальным сценарием, я решил покопаться и посмотреть, не упустил ли я чего-то.

Путем проб и ошибок я обнаружил, что следующий код будет делать именно то, что я хотел;

ConfigurationManager.AppSettings.Set(key_name, data_value)

Используя эту строку кода, я теперь могу загрузить все 85 ключей appSettings из ZooKeeper в свой Application_Start.

Что касается общих утверждений об изменениях в web.config, запускающих повторное использование IIS, я отредактировал следующие параметры appPool, чтобы отслеживать ситуацию за кулисами;

appPool-->Advanced Settings-->Recycling-->Disable Recycling for Configuration Changes = False
appPool-->Advanced Settings-->Recycling-->Generate Recycle Event Log Entry-->[For Each Setting] = True

С такой комбинацией настроек, если этот процесс должен был вызвать перезапуск appPool, запись в журнале событий должна была быть записана, чего не было.

Это приводит меня к выводу, что можно и действительно безопасно загружать настройки приложений с централизованного носителя данных.

Я должен упомянуть, что я использую IIS7.5 в Windows 7. Код будет развернут в IIS8 в Win2012. Если что-то в этом ответе изменится, я соответствующим образом обновлю этот ответ.

Шалфей
источник
Это, вероятно, сэкономило мне несколько часов. Спасибо!
Дрю Делано
4

Кому нравится прямо в точку,

В вашей конфигурации

    <appSettings>

    <add key="Conf_id" value="71" />

  </appSettings>

в вашем коде (c #)

///SET
    ConfigurationManager.AppSettings.Set("Conf_id", "whateveryourvalue");
      ///GET              
    string conf = ConfigurationManager.AppSettings.Get("Conf_id").ToString();
mzonerz
источник
0

Попробуй это:

using System;
using System.Configuration;
using System.Web.Configuration;

namespace SampleApplication.WebConfig
{
    public partial class webConfigFile : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            //Helps to open the Root level web.config file.
            Configuration webConfigApp = WebConfigurationManager.OpenWebConfiguration("~");
            //Modifying the AppKey from AppValue to AppValue1
            webConfigApp.AppSettings.Settings["ConnectionString"].Value = "ConnectionString";
            //Save the Modified settings of AppSettings.
            webConfigApp.Save();
        }
    }
}
Выпускники кода
источник