Como você modifica o web.config appSettings em tempo de execução?

84

Estou confuso sobre como modificar os valores web.config appSettings em tempo de execução. Por exemplo, tenho esta seção 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>

Digamos que eu queira modificar a chave "homepagedesc" em tempo de execução. Tentei as classes estáticas ConfigurationManager e WebConfigurationManager, mas as configurações são "somente leitura". Como modifico os valores de appSettings em tempo de execução?

ATUALIZAÇÃO: Ok, então aqui estou 5 anos depois. Gostaria de salientar que a experiência me disse que não devemos colocar nenhuma configuração que seja intencionalmente editável em tempo de execução no arquivo web.config, mas, em vez disso, devemos colocá-la em um arquivo XML separado, conforme um dos usuários comentou abaixo. Isso não exigirá nenhuma edição do arquivo web.config para reiniciar o aplicativo, o que resultará em usuários irritados ligando para você.

jerbersoft
fonte
Aqui está um bom link que explica muito bem como modificar o web.config em tempo de execução e seu impacto no aplicativo. http://aspdotnethacker.blogspot.com/2010/05/modify-webconfig-file-at-runtime.html
5
@ user330004 o link que você forneceu não é mais válido
McArthey
Leva apenas alguns segundos para encontrar a versão arquivada !
stuartd

Respostas:

84

Você precisa usar WebConfigurationManager.OpenWebConfiguration(): Por exemplo:

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

Acho que você também pode precisar definir AllowLocation em machine.config. Este é um valor booleano que indica se páginas individuais podem ser configuradas usando o elemento. Se "allowLocation" for falso, ele não pode ser configurado em elementos individuais.

Finalmente, faz diferença se você executar seu aplicativo no IIS e executar seu exemplo de teste no Visual Studio. A identidade do processo ASP.NET é a conta IIS, ASPNET ou NETWORK SERVICES (dependendo da versão do IIS).

Pode ser necessário conceder acesso ASPNET ou NETWORK SERVICES para Modificar na pasta onde o web.config reside.

Trigo mitch
fonte
1
Obrigado pela resposta Mitch. Você respondeu minha pergunta. O que fiz foi executar o VS 2008 como administrador e tudo estava indo bem.
jerbersoft,
Talvez óbvio para os outros (não para mim), esta resposta, assim como a de Amin, que é funcionalmente a mesma, na verdade sobrescreve seu arquivo físico web.config, não apenas sobrescreve a configuração na memória para a instância em execução específica.
k3davis
24

Alterar o web.config geralmente causa a reinicialização do aplicativo.

Se você realmente precisa que seu aplicativo edite suas próprias configurações, deve considerar uma abordagem diferente, como banco de dados das configurações ou criação de um arquivo xml com as configurações editáveis.

Joel
fonte
1
Oi, obrigado pela resposta. Mas existe essa classe de "Configuração" que tem uma função "Salvar". Você realmente precisa reiniciar o aplicativo para que as novas configurações fiquem ativas?
jerbersoft,
4
Alterar o web.config dispara automaticamente a reinicialização do aplicativo.
Mike Cole
1
Alterar o web.config dinamicamente não deve ser recomendado. Eu preferiria armazenar o valor em um arquivo (xml).
Deepak Mishra
alguém pode explicar por que reiniciar o aplicativo é ruim e muitos recomendam mover o atributo para um arquivo diferente?
Ben
1
@Ben - Eu sei que já se passaram alguns meses, mas apenas no caso - reiniciar o aplicativo significará que qualquer pessoa conectada ao seu aplicativo no ponto de reinicialização será desconectada automaticamente e provavelmente encontrará um erro. (vários cenários, como web farms ...). usuários irritados contatam o suporte, o suporte contata você etc etc etc ...
Fetchez la vache
24

E se quiser evitar o reinício do aplicativo, você pode mover a appSettingsseção:

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

para um arquivo separado. E em combinação comConfigurationSaveMode.Minimal

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

você pode continuar a usar a appSettingsseção como o armazenamento de várias configurações sem causar reinicializações do aplicativo e sem a necessidade de usar um arquivo com um formato diferente do que a seção appSettings normal.

Ciprian Teiosanu
fonte
22

2012 Esta é a melhor solução para este cenário (testado com Visual Studio 2008 ):

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

Atualização 2018 =>
Testado em vs 2015 - Asp.net MVC5

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

se você precisar verificar se o elemento existe, use este código:

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
fonte
Você poderia explicar um pouco por que é melhor? Eu sei que as coisas do configSection às vezes são um pouco complicadas.
julealgon
1
Este código é menor e mais compreensível! Pelo menos para mim.
Amin Ghaderi
3
Oh, é por causa do gosto pessoal então, eu realmente pensei que era logicamente diferente de alguma forma. Eu discordo totalmente de você neste caso por uma série de razões: primeiro porque você tem que especificar a mesma chave duas vezes, segundo porque o que você está fazendo é semanticamente diferente do que é realmente necessário ('atualizar' vs 'remover-> add ') e terceiro porque o código é realmente mais longo (não sei por que você pensa de outra forma aqui) e aberto a erros. Além disso, e se por algum motivo seu código falhar entre as chamadas? Seu aplicativo está quebrado a partir daí, eu acho.
julealgon 01 de
2
Este código apaga qualquer comentário irmão de MyVariable.
Blagus
Sim, exatamente ! Este código de código pode ser reescrito todas as variáveis, mas funciona. mas eu não recomendo usá-lo, quando você usou o código de comentário. Obrigado.
Amin Ghaderi de
14

Sei que essa pergunta é antiga, mas gostaria de postar uma resposta com base no estado atual das coisas no mundo ASP.NET \ IIS combinado com minha experiência no mundo real.

Recentemente, liderei um projeto em minha empresa em que queria consolidar e gerenciar todas as configurações de appSettings e connectionStrings em nossos arquivos web.config em um local central. Eu queria seguir uma abordagem em que nossas configurações fossem armazenadas no ZooKeeper devido à maturidade e estabilidade desse projeto. Sem mencionar o fato de que o ZooKeeper é por design um aplicativo de gerenciamento de configuração e cluster.

Os objetivos do projeto eram muito simples;

  1. faça o ASP.NET se comunicar com o ZooKeeper
  2. em Global.asax, Application_Start - extraia as configurações web.config do ZooKeeper.

Depois de passar pela parte técnica de fazer o ASP.NET falar com o ZooKeeper, rapidamente descobri e bati na parede com o código a seguir;

ConfigurationManager.AppSettings.Add(key_name, data_value)

Essa declaração fez o sentido mais lógico, pois eu queria ADICIONAR novas configurações à coleção appSettings. No entanto, como o autor da postagem original (e muitos outros) mencionou, essa chamada de código retorna um erro informando que a coleção é somente leitura.

Depois de fazer um pouco de pesquisa e ver todas as maneiras diferentes e malucas com as quais as pessoas contornavam esse problema, fiquei muito desanimado. Em vez de desistir ou se contentar com o que parecia ser um cenário menos do que o ideal, decidi cavar e ver se estava faltando alguma coisa.

Com um pouco de tentativa e erro, descobri que o código a seguir faria exatamente o que eu queria;

ConfigurationManager.AppSettings.Set(key_name, data_value)

Usando esta linha de código, agora consigo carregar todas as 85 chaves appSettings do ZooKeeper em meu Application_Start.

Com relação às declarações gerais sobre as alterações no web.config que acionam as reciclagens do IIS, editei as seguintes configurações de appPool para monitorar a situação nos bastidores;

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

Com essa combinação de configurações, se esse processo causasse uma reciclagem de appPool, uma entrada do Log de eventos deveria ser registrada, o que não foi.

Isso me leva a concluir que é possível, e de fato seguro, carregar as configurações de um aplicativo a partir de um meio de armazenamento centralizado.

Devo mencionar que estou usando o IIS7.5 no Windows 7. O código será implantado no IIS8 no Win2012. Se algo em relação a essa resposta mudar, atualizarei esta resposta de acordo.

Sábio
fonte
Isso provavelmente só me salvou algumas horas. Muito obrigado!
Drew Delano
4

Quem gosta direto ao ponto,

Em sua configuração

    <appSettings>

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

  </appSettings>

em seu código (c #)

///SET
    ConfigurationManager.AppSettings.Set("Conf_id", "whateveryourvalue");
      ///GET              
    string conf = ConfigurationManager.AppSettings.Get("Conf_id").ToString();
mzonerz
fonte
0

Experimente isto:

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();
        }
    }
}
Ex-alunos do código
fonte