Usando o ConfigurationManager para carregar a configuração de um local arbitrário
-
08-06-2019 - |
Pergunta
Estou desenvolvendo um componente de acesso a dados que será usado em um site que contém uma mistura de páginas clássicas ASP e ASP.NET e precisa de uma boa maneira de gerenciar suas configurações.
Eu gostaria de usar um personalizado ConfigurationSection
, e para páginas ASP.NET isso funciona muito bem.Mas quando o componente é chamado via interoperabilidade COM a partir de uma página ASP clássica, o componente não está em execução no contexto de uma solicitação ASP.NET e, portanto, não tem conhecimento de web.config.
Existe uma maneira de dizer ao ConfigurationManager
para apenas carregar a configuração de um caminho arbitrário (por exemplo, ..\web.config
se minha assembléia estiver no /bin
pasta)?Se houver, estou pensando que meu componente pode voltar a isso se o padrão ConfigurationManager.GetSection
retorna null
para minha seção personalizada.
Quaisquer outras abordagens para isso seriam bem-vindas!
Solução
Experimente isto:
System.Configuration.ConfigurationFileMap fileMap = new ConfigurationFileMap(strConfigPath); //Path to your config file
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
Outras dicas
Outra solução é substituir o caminho do arquivo de configuração do ambiente padrão.
Acho que é a melhor solução para o carregamento do arquivo de configuração de caminho não trivial, especificamente a melhor maneira de anexar o arquivo de configuração à dll.
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", <Full_Path_To_The_Configuration_File>);
Exemplo:
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", @"C:\Shared\app.config");
Mais detalhes podem ser encontrados em este blog.
Adicionalmente, esta outra resposta tem uma excelente solução, completa com código para atualizar a configuração do aplicativo e um IDisposable
objeto para redefini-lo de volta ao seu estado original.Com esta solução, você pode manter o aplicativo temporário Scoped:
using(AppConfig.Change(tempFileName))
{
// tempFileName is used for the app config during this context
}
A resposta de Ismaeel geralmente funciona, mas encontrei um problema: usar OpenMappedMachineConfiguration
parece perder seus grupos de seções herdados de machine.config.Isso significa que você pode acessar suas próprias seções personalizadas (que é tudo o que o OP deseja), mas não as seções normais do sistema.Por exemplo, este código não funcionará:
ConfigurationFileMap fileMap = new ConfigurationFileMap(strConfigPath);
Configuration configuration = ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
MailSettingsSectionGroup thisMail = configuration.GetSectionGroup("system.net/mailSettings") as MailSettingsSectionGroup; // returns null
Basicamente, se você colocar um relógio no configuration.SectionGroups
, você verá que system.net não está registrado como SectionGroup, portanto é praticamente inacessível pelos canais normais.
Encontrei duas maneiras de contornar isso.A primeira, da qual não gosto, é reimplementar os grupos de seções do sistema, copiando-os de machine.config para seu próprio web.config, por exemplo.
<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>
Não tenho certeza se o aplicativo da web será executado corretamente depois disso, mas você pode acessar a seçãoGroups corretamente.
A segunda solução é abrir seu web.config como uma configuração EXE, que provavelmente está mais próxima da função pretendida:
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!
Ouso dizer que nenhuma das respostas fornecidas aqui, nem a minha nem a de Ishmaeel, estão usando essas funções como os designers do .NET pretendiam.Mas isso parece funcionar para mim.
Além da resposta de Ismaeel, o método OpenMappedMachineConfiguration()
sempre retornará um Configuration
objeto.Então, para verificar se ele carregou, você deve verificar o HasFile
propriedade onde true significa que veio de um arquivo.
Forneci os valores de configuração para o Word hospedado .nET Compoent da seguinte maneira.
Um componente da biblioteca de classes .NET sendo chamado/hospedado no MS Word.Para fornecer valores de configuração ao meu componente, criei winword.exe.config na pasta C:\Program Files\Microsoft Office\OFFICE11.Você deve ser capaz de ler os valores das configurações como faz no .NET tradicional.
string sMsg = System.Configuration.ConfigurationManager.AppSettings["WSURL"];
A resposta aceita está errada!!
Ele lança a seguinte exceção ao acessar a propriedade AppSettings:
Não é possível converter o objeto do tipo 'System.Configuration.DefaultSection' para o tipo 'System.Configuration.AppSettingsSection'.
Aqui está a solução correta:
System.Configuration.ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = "YourFilePath";
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
Para ASP.NET use WebConfigurationManager:
var config = WebConfigurationManager.OpenWebConfiguration("~/Sites/" + requestDomain + "/");
(..)
config.AppSettings.Settings["xxxx"].Value;
Use processamento XML:
var appPath = AppDomain.CurrentDomain.BaseDirectory;
var configPath = Path.Combine(appPath, baseFileName);;
var root = XElement.Load(configPath);
// can call root.Elements(...)
Isso deve funcionar:
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", "newAppConfig.config);
Fonte : https://www.codeproject.com/Articles/616065/Why-Where-and-How-of-NET-Configuration-Files