Jak zmodyfikować web.config appSettings w czasie wykonywania?

84

Nie wiem, jak zmodyfikować wartości appSettings web.config w czasie wykonywania. Na przykład mam tę sekcję 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>

Powiedzmy, że chcę zmodyfikować klucz „homepagedesc” w czasie wykonywania. Wypróbowałem klasy statyczne ConfigurationManager i WebConfigurationManager, ale ustawienia są „tylko do odczytu”. Jak zmodyfikować wartości appSettings w czasie wykonywania?

AKTUALIZACJA: Ok, więc oto jestem 5 lat później. Chciałbym zwrócić uwagę, że doświadczenie podpowiada mi, że nie powinniśmy umieszczać żadnej konfiguracji, którą celowo można edytować w czasie wykonywania, w pliku web.config, ale zamiast tego powinniśmy umieścić ją w oddzielnym pliku XML, tak jak skomentował to jeden z użytkowników poniżej. Nie będzie to wymagało żadnej edycji pliku web.config w celu ponownego uruchomienia aplikacji, co spowoduje, że wściekli użytkownicy będą do Ciebie dzwonić.

jerbersoft
źródło
Oto dobry link, który ładnie wyjaśnia, jak modyfikować plik web.config w czasie wykonywania i jaki ma to wpływ na aplikację. http://aspdotnethacker.blogspot.com/2010/05/modify-webconfig-file-at-runtime.html
5
@ user330004, podany przez Ciebie link nie jest już ważny
McArthey
Znalezienie zarchiwizowanej wersji zajmuje tylko kilka sekund !
stuartd

Odpowiedzi:

84

Musisz użyć WebConfigurationManager.OpenWebConfiguration(): Na przykład:

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

Myślę, że może być konieczne ustawienie AllowLocation w machine.config. Jest to wartość logiczna, która wskazuje, czy poszczególne strony można konfigurować za pomocą elementu. Jeśli parametr „allowLocation” ma wartość false, nie można go skonfigurować w poszczególnych elementach.

Wreszcie, ma znaczenie, jeśli uruchomisz aplikację w usługach IIS i uruchomisz próbkę testową z programu Visual Studio. Tożsamość procesu ASP.NET to konto IIS, ASPNET lub USŁUGI SIECIOWE (w zależności od wersji IIS).

Może być konieczne przyznanie usług ASPNET lub USŁUGI SIECIOWE Modyfikacja dostępu do folderu, w którym znajduje się plik web.config.

Mitch Wheat
źródło
1
Dzięki za odpowiedź Mitch. Odpowiedziałeś na moje pytanie. Uruchomiłem VS 2008 jako Administrator i wszystko szło dobrze.
jerbersoft
Być może oczywiste dla innych (nie dla mnie), ta odpowiedź, podobnie jak Amin, która jest funkcjonalnie taka sama, w rzeczywistości nadpisuje twój fizyczny plik web.config, nie tylko zastępuje ustawienia w pamięci dla konkretnej uruchomionej instancji.
k3davis
24

Zmiana pliku web.config zazwyczaj powoduje ponowne uruchomienie aplikacji.

Jeśli naprawdę potrzebujesz aplikacji do edycji własnych ustawień, powinieneś rozważyć inne podejście, takie jak bazy danych ustawień lub utworzenie pliku xml z edytowalnymi ustawieniami.

Joel
źródło
1
Cześć, dzięki za odpowiedź. Ale istnieje klasa „Konfiguracja”, która ma funkcję „Zapisz”. Czy naprawdę musisz ponownie uruchomić aplikację, aby nowe ustawienia były aktywne?
jerbersoft
4
Zmiana pliku web.config automatycznie uruchamia ponowne uruchomienie aplikacji.
Mike Cole,
1
Nie zaleca się dynamicznej zmiany pliku web.config. Wolałbym przechowywać wartość w pliku (xml).
Deepak Mishra
Czy ktoś może wyjaśnić, dlaczego ponowne uruchamianie aplikacji jest złe i wielu zaleca przeniesienie atrybutu do innego pliku?
Ben
1
@Ben - wiem, że minęło kilka miesięcy, ale na wszelki wypadek - ponowne uruchomienie aplikacji spowoduje, że każdy zalogowany do Twojej aplikacji w momencie ponownego uruchomienia zostanie automatycznie wylogowany i najprawdopodobniej napotka błąd. (niezależnie od różnych scenariuszy, takich jak farmy internetowe ...). zły użytkowników kontaktu wsparcia, wspierające kontakty, etc etc etc ...
Fetchez la vache
24

A jeśli chcesz uniknąć ponownego uruchamiania aplikacji, możesz przenieść appSettingssekcję:

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

do osobnego pliku. I w połączeniu zConfigurationSaveMode.Minimal

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

możesz nadal używać tej appSettingssekcji jako magazynu dla różnych ustawień bez powodowania ponownego uruchamiania aplikacji i bez konieczności używania pliku o innym formacie niż normalna sekcja appSettings.

Ciprian Teiosanu
źródło
21

2012 To jest lepsze rozwiązanie dla tego scenariusza (przetestowane w programie Visual Studio 2008 ):

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

Aktualizacja 2018 =>
Testowane w porównaniu z 2015 r. - Asp.net MVC5

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

jeśli potrzebujesz sprawdzić, czy element istnieje, użyj tego kodu:

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();
Amin Ghaderi
źródło
Czy mógłbyś trochę wyjaśnić, dlaczego jest lepiej? Wiem, że rzeczy z configSection są czasami trudne.
julealgon
1
Ten kod jest mniejszy i bardziej zrozumiały! Przynajmniej dla mnie.
Amin Ghaderi,
3
Och, to z powodu osobistego gustu, właściwie myślałem, że jest to logicznie różne. Zdecydowanie nie zgadzam się z tobą w tym przypadku, chociaż właściwie z kilku powodów: po pierwsze, ponieważ musisz podać ten sam klucz dwa razy, po drugie, ponieważ to, co robisz, jest semantycznie inne niż to, co jest faktycznie potrzebne („aktualizacja” vs add ') i po trzecie, ponieważ kod jest w rzeczywistości dłuższy (nie wiem, dlaczego myślisz inaczej) i otwarty na błędy. A co jeśli z jakiegoś powodu twój kod zawiedzie między wywołaniami? Myślę, że od tego momentu Twoja aplikacja jest zepsuta.
julealgon
2
Ten kod usuwa wszelkie komentarze równorzędne z MyVariable.
blagus
Tak, dokładnie ! Ten kod kodu został przepisany na wszystkie zmienne, ale działa. ale nie polecam go używać, gdy używasz kodu komentarza. Dziękuję Ci.
Amin Ghaderi,
14

Wiem, że to pytanie jest stare, ale chciałem zamieścić odpowiedź w oparciu o aktualny stan rzeczy w świecie ASP.NET \ IIS w połączeniu z moimi doświadczeniami w świecie rzeczywistym.

Niedawno prowadziłem projekt w mojej firmie, w którym chciałem skonsolidować i zarządzać wszystkimi ustawieniami appSettings i connectionStrings w naszych plikach web.config w jednym centralnym miejscu. Chciałem zastosować podejście, w którym nasze ustawienia konfiguracyjne były przechowywane w ZooKeeper ze względu na dojrzałość i stabilność projektu. Nie wspominając o tym, że ZooKeeper jest z założenia aplikacją do konfiguracji i zarządzania klastrem.

Cele projektu były bardzo proste;

  1. uzyskać ASP.NET do komunikacji z ZooKeeper
  2. w Global.asax, Application_Start - ściągnij ustawienia web.config z ZooKeepera.

Po przejściu części technicznej związanej z rozmową ASP.NET z ZooKeeperem, szybko znalazłem i uderzyłem w ścianę za pomocą następującego kodu;

ConfigurationManager.AppSettings.Add(key_name, data_value)

To stwierdzenie miało najbardziej logiczny sens, ponieważ chciałem dodać nowe ustawienia do kolekcji appSettings. Jednak, jak wspomniano w oryginalnym plakacie (i wielu innych), to wywołanie kodu zwraca błąd stwierdzający, że kolekcja jest tylko do odczytu.

Po przeprowadzeniu trochę badań i zobaczeniu różnych szalonych sposobów, w jakie ludzie radzili sobie z tym problemem, byłem bardzo zniechęcony. Zamiast się poddać lub poprzestać na tym, co wydawało się być mało idealnym scenariuszem, zdecydowałem się zagłębić i sprawdzić, czy czegoś mi brakuje.

Po kilku próbach i błędach stwierdziłem, że następujący kod zrobi dokładnie to, co chciałem;

ConfigurationManager.AppSettings.Set(key_name, data_value)

Korzystając z tej linii kodu, mogę teraz załadować wszystkie 85 kluczy appSettings z ZooKeeper w moim Application_Start.

Jeśli chodzi o ogólne stwierdzenia dotyczące zmian w pliku web.config powodujących ponowne uruchomienie usług IIS, zmodyfikowałem następujące ustawienia puli aplikacji, aby monitorować sytuację za kulisami;

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

Przy takiej kombinacji ustawień, jeśli ten proces miałby spowodować ponowne odtworzenie puli aplikacji, wpis w dzienniku zdarzeń powinien zostać zarejestrowany, a nie był.

To prowadzi mnie do wniosku, że ładowanie ustawień aplikacji ze scentralizowanego nośnika pamięci jest możliwe i rzeczywiście bezpieczne.

Powinienem wspomnieć, że używam IIS7.5 w systemie Windows 7. Kod zostanie wdrożony w IIS8 na Win2012. Jeśli cokolwiek w tej odpowiedzi ulegnie zmianie, odpowiednio zaktualizuję tę odpowiedź.

szałwia
źródło
To prawdopodobnie zaoszczędziło mi kilku godzin. Dzięki wielkie!
Drew Delano
4

Kto lubi bezpośrednio do rzeczy,

W twojej konfiguracji

    <appSettings>

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

  </appSettings>

w swoim kodzie (C #)

///SET
    ConfigurationManager.AppSettings.Set("Conf_id", "whateveryourvalue");
      ///GET              
    string conf = ConfigurationManager.AppSettings.Get("Conf_id").ToString();
mzonerz
źródło
0

Spróbuj tego:

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();
        }
    }
}
Code Alumni
źródło