Desenvolvimento - ASP. NET
Manipulando o Web.Config Sem Causar o Restart da Aplicação
Usualmente gravamos diversas configurações no web.config na tag appSettings que são utilizadas em nossas aplicações. É comum receber e-mail ou perguntas pelo MSN com a seguinte questão: Como se pode criar uma interface para alterar e manipular estes parâmetros do web.config em tempo de execução pela aplicação.
por Fernando CerqueiraUsualmente gravamos diversas configurações no web.config na tag appSettings que são utilizadas em nossas aplicações. É comum receber e-mail ou perguntas pelo MSN com a seguinte questão:
“Como se pode criar uma interface para alterar e manipular estes parâmetros do web.config em tempo de execução pela aplicação”
Esta pergunta esbarra em dois cenários que devem ser resolvidos:
1) Qualquer alteração no web.config
causa um "restart" da aplicação, o que inviabiliza este tipo de construção.
2) É comum é termos parâmetros distintos
para o ambiente de produção e o ambiente de desenvolvimento, sendo necessário também
modificar o web.config quando trocamos de ambiente.
Algumas novas características foram introduzidas no framework 2,0 que permitem resolver ambos os cenários de forma bastante eficiente.
Resolvendo o primeiro Cenário:
Alterar o web.config na tag appSettings sem causar o restart da aplicação
Temos agora no framework 2.0 um novo atributo para a tag appSettings :
configSource – Informar um caminho relativo de um arquivo para definição da uma sessão executando um include em tempo de execução.
Este atributo pode ser aplicado em qualquer sessão do web.config porem causa o restart da aplicação quando o arquivo externo é alterado, com exceção de uma única sessão :AppSetting!
Quando se define este atributo não pode existir mais nenhum outro atributo na sessão. Vejamos o exemplo abaixo:
Arquivo web.config:
<configuration>
<appSettings configSource="AppSettings.config"/>
<connectionStrings/>
. . .
Arquivo AppSettings.config:
<appSettings >
<add key="AppAmbiente" value="Desenvolvimento" />
</appSettings>
Para testar basta criar um formulário que recupere a key “AppAmbiente”. Depois que estiver executando altere o arquivo AppSettings.config e recupere novamente a key “AppAmbiente” . Vai perceber que o valor retornado será o valor alterado sem sua aplicação execute um restart!
Você deve estar se perguntando por
que somente a sessão
AppSettings não causa o
restart da aplicação... Esta pergunta é respondida descrevendo outro atributo que
foi introduzindo no framework 2.0:
restartOnExternalChanges. Este atributo destina-se as definições de
sessões informando se uma sessão (que aceita uma definição externa) executa um “restart” na aplicação quando ocorre uma alteração
no arquivo externo que foi informado.
A definição as sessão
AppSettings é feita no arquivo de configuração
machine.config e tem a seguinte assinatura:
<section name="appSettings" type="System.Configuration.AppSettingsSection,
System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
restartOnExternalChanges="false"
requirePermission="false" />
Isso explica o motivo de não ocorrer o restart
na aplicação quando é feito uma alteração no arquivo externo ao web.config.
:
File - Informar um caminho relativo de um arquivo para definição da sessão appsetting
executando merge em tempo de execução. Caso o arquivo não exista não é executado
o merge e ignorado a informação de arquivo.
Como é feito o Merge entre o que existe já definido com as key’s/valores do arquivo informado no atributo File (caso exista) resolvemos o segundo cenário:
- Na maquina de desenvolvimento Não deve existir. Assim a informação do atributo file é ignorado e mantido os valores.
- Na máquina de produção
o arquivo Deve existir. Assim a informação do atributo
file é executado.
Resolvendo o Primeiro e Segundo Cenário juntos:
Conhecendo agora os dois novos atributos (file e configSource) fica fácil criar uma única abordagem para resolver os dois cenários:
Arquivo web.config:
<configuration>
<appSettings configSource="AppSettings.config"/>
<connectionStrings/>
. . .
Arquivo AppSettings.config:
<appSettings file="AppSettingsProducao.config">
<add key="AppAmbiente" value="Desenvolvimento" />
</appSettings>
Arquivo AppSettingsProducao.config:
<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
<clear/>
<add key="AppAmbiente" value="Produção" />
</appSettings>
Detalhes
do funcionamento na máquina de Produção:
1) Quando a aplicação é inicializada a aplicação lê o arquivo web.config que informa
que a leitura da sessão AppSettings
devera ser feita no arquivo
AppSettings.config e incluída
no web.config.
2) Durante a leitura do arquivo AppSettings.config a aplicação é informada que existe outro arquivo externo (AppSettingsProducao.config) para ser feito um merge.
3) O arquivo é localizado e após a execução do merge a key “AppAmbiente” recebe o valor "Produção"
Detalhes
do funcionamento na máquina de Desenvolvimento:
1) Quando a aplicação é inicializada a aplicação lê o arquivo web.config que informa
que a leitura da sessão AppSettings
devera ser feita no arquivo
AppSettings.config e incluída
no web.config.
2) Durante a leitura do arquivo AppSettings.config a aplicação é informada que existe outro arquivo externo (AppSettingsDesenv.config) para ser feito um merge.
3) O arquivo NÃO É LOCALIZADO (não deve existir em desenvolvimento) e é ignorada a execução do merge e a key “AppAmbiente” mantem o valor "Desenvolvimento"
Aplicação de Exemplo:
Antes de terminar vamos mostrar um exemplo passo a passo de todo o conceito para ficar mais claro:
1) Crie uma aplicação web no Visual Studio Express
2) Altere o web.config na tag : <appSettings configSource="AppSettings.config"/>
3) Adicione a solução um arquivo XML com o nome: AppSettings.config
4) Inclua as linhas abaixo no arquivo AppSettings.config
<?xml version="1.0" encoding="utf-8" ?>
<appSettings file="AppSettingsProducao.config.off">
<add key="AppAmbiente" value="Desenvolvimento" />
</appSettings>
5) Adicione a solução um arquivo XML com o nome: AppSettingsProducao.config
6) Inclua as linhas abaixo no arquivo AppSettingsProducao.config
<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
<clear/>
<add key="AppAmbiente" value="Produção" />
</appSettings>
7) Adicione a solução um arquivo global.asax
8) Inclua o código abaixo no arquivo global.asax
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
Application("Status") = " Aplicação foi feita restart"
End Sub
9) Inclua o código dentro da <DIV> abaixo dentro do arquivo default.aspx
<form id="form1" runat="server">
<div>
Application Evento Start :
<asp:Label ID="Label3" runat="server" Text=""></asp:Label><br />
Sessão :
<asp:Label ID="Label2" runat="server" Text=""></asp:Label><br />
Ambiente :
<asp:Label ID="Label1" runat="server" Text=""></asp:Label> <br />
<br />
<asp:Button ID="Button1" runat="server" Text="Atualizar" />
</div>
</form>
10)Inclua na classe do formulário o código abaixo:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
Session("VarSession") = Session.SessionID
VerTeste()
End If
End Sub
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
VerTeste()
End Sub
Private Sub VerTeste()
Me.Label1.Text = ConfigurationManager.AppSettings("AppAmbiente").ToString
Me.Label2.Text = Session("VarSession")
Me.Label3.Text = Application("Status")
Application("Status") = "Aplicação Sem Restart"
End Sub
11)Compile a aplicação e execute
12)Altere o conteúdo key="AppAmbiente" no arquivo AppSettings.config e salve
13)Clique no botão de Atualizar
14)Altere o conteúdo file="AppSettingsProducao.config.off" para file="AppSettingsProducao.config" e salve
15)Clique no botão de Atualizar
Indo um pouco além:
Se observar com atenção já percebeu que com esta estrutura proposta podemos ter
múltiplos arquivos de configuração na produção podendo escolher entre eles apenas
alterado o atributo
FILE. Este
recurso expande as possibilidades de configuração da aplicação, mas
podemos ir alem.
No inicio do artigo falamos de dois atributos (configSource e
restartOnExternalChanges). O primeiro atributo (configSource) pode ser definido
no arquivo web.config para algumas tag’s
:
AppSettings , connectionStrings , siteMap , membership , smtpMail etc. Uma
lista completa pode ser encontrada no SDK do produto.
O segundo atributo
restartOnExternalChanges pode ser definido no
web.config para sessões customizada.
As sessões default / padrão do framework definidas pelo arquivo
machine.config não podem ser alteradas no
web.config , porem podemos alterar estas definições no próprio arquivo
machine.config permitindo alterar os
arquivos externos sem causar o restart da aplicação.
Deve ficar claro para o desenvolvedor que estas alterações no arquivo
machine.config terá efeito
para todas as aplicações que rodam sobre o IIS onde esta instalado o framework.
Outro ponto importante é saber exatamente o efeito que uma alteração dinâmica pode
causar. Um exemplo é a connectionStrings
: Para deixar ela com o mesmo comportamento
do AppSettings basta alterar a linha
para :
<section name="connectionStrings" type="System.Configuration.ConnectionStringsSection, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" requirePermission="false" restartOnExternalChanges="false" />
A principal pergunta quando alterar neste exemplo o comportamento é: Se houve uma alteração da string de conexão provavelmente você estará acessando outro banco... O que acontece se isso ocorrer no meio de um processo onde já possui dado e executado a lógica baseado em resultados provenientes do banco anterior?
A idéia aqui é demonstrar que podemos com pouco esforço deixar o framework e a configuração bem mais flexível, porem as implicações de mudanças dinâmicas deve ser pensado de forma criteriosa para garantir a consistência dos dados, interfaces e processos da aplicação.
Conclusão:
Devido às novas características introduzidas no framework 2.0 o desenvolvedor passou a contar com recursos de configurações mais poderosos e dinâmicos, sendo possível criar as interfaces para leitura dos arquivos XML de configuração e executar alterações em tempo de execução. Alem desta facilidade tornou-se possível manter ambientes distintos sem a necessidade de se alterar valores de chaves em arquivos de configuração evitando-se assim erros comuns causados pelo “esquecimento” ou alteração indevida destas chaves.