Utilizzo di ConfigurationManager per caricare la configurazione da una posizione arbitraria
-
08-06-2019 - |
Domanda
Sto sviluppando un componente di accesso ai dati che verrà utilizzato in un sito Web che contiene un mix di pagine ASP e ASP.NET classiche e necessito di un buon modo per gestirne le impostazioni di configurazione.
Vorrei usare un'abitudine ConfigurationSection
, e per le pagine ASP.NET funziona benissimo.Ma quando il componente viene chiamato tramite interoperabilità COM da una pagina ASP classica, il componente non viene eseguito nel contesto di una richiesta ASP.NET e pertanto non conosce web.config.
C'è un modo per dirlo ConfigurationManager
per caricare semplicemente la configurazione da un percorso arbitrario (ad es. ..\web.config
se la mia assemblea è nel /bin
cartella)?Se c'è, allora penso che il mio componente possa ricorrere a quello predefinito ConfigurationManager.GetSection
ritorna null
per la mia sezione personalizzata.
Qualsiasi altro approccio a questo sarebbe il benvenuto!
Soluzione
Prova questo:
System.Configuration.ConfigurationFileMap fileMap = new ConfigurationFileMap(strConfigPath); //Path to your config file
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
Altri suggerimenti
Un'altra soluzione consiste nell'override del percorso del file di configurazione dell'ambiente predefinito.
Trovo che sia la soluzione migliore per il caricamento del file di configurazione con percorso non banale, in particolare il modo migliore per allegare il file di configurazione alla DLL.
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", <Full_Path_To_The_Configuration_File>);
Esempio:
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", @"C:\Shared\app.config");
Maggiori dettagli possono essere trovati su questo blog.
Inoltre, quest'altra risposta ha una soluzione eccellente, completa di codice per aggiornare la configurazione dell'app e un IDisposable
oggetto per ripristinarlo al suo stato originale.Con questa soluzione, è possibile conservare la configurazione di app temporanea con ambito:
using(AppConfig.Change(tempFileName))
{
// tempFileName is used for the app config during this context
}
La risposta di Ishmaeel generalmente funziona, tuttavia ho riscontrato un problema, ovvero l'utilizzo OpenMappedMachineConfiguration
sembra perdere i gruppi di sezioni ereditati da machine.config.Ciò significa che puoi accedere alle tue sezioni personalizzate (che è tutto ciò che l'OP desidera), ma non alle normali sezioni di sistema.Ad esempio, questo codice non funzionerà:
ConfigurationFileMap fileMap = new ConfigurationFileMap(strConfigPath);
Configuration configuration = ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
MailSettingsSectionGroup thisMail = configuration.GetSectionGroup("system.net/mailSettings") as MailSettingsSectionGroup; // returns null
Fondamentalmente, se metti un orologio sul configuration.SectionGroups
, vedrai che system.net non è registrato come SezioneGroup, quindi è praticamente inaccessibile tramite i normali canali.
Ci sono due modi che ho trovato per aggirare questo problema.Il primo, che non mi piace, è reimplementare i gruppi di sezioni di sistema copiandoli da machine.config nel tuo web.config, ad es.
<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>
Non sono sicuro che l'applicazione web stessa funzionerà correttamente dopo, ma puoi accedere correttamente alla sezione Gruppi.
La seconda soluzione è invece aprire il tuo web.config come configurazione EXE, che probabilmente è comunque più vicina alla sua funzione prevista:
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!
Oserei dire che nessuna delle risposte fornite qui, né la mia né quella di Ishmaeel, utilizzano queste funzioni come intendevano i progettisti .NET.Ma questo sembra funzionare per me.
Oltre alla risposta di Ishmaeel, il metodo OpenMappedMachineConfiguration()
restituirà sempre a Configuration
oggetto.Quindi per verificare se è stato caricato dovresti controllare il file HasFile
proprietà dove true significa che proviene da un file.
Ho fornito i valori di configurazione al componente .nET ospitato da Word come segue.
Un componente della libreria di classi .NET chiamato/ospitato in MS Word.Per fornire valori di configurazione al mio componente, ho creato winword.exe.config nella cartella C:\Programmi\Microsoft Office\OFFICE11.Dovresti essere in grado di leggere i valori di configurazione come fai in .NET tradizionale.
string sMsg = System.Configuration.ConfigurationManager.AppSettings["WSURL"];
La risposta accettata è sbagliata!!
Genera la seguente eccezione quando si accede alla proprietà AppSettings:
Impossibile eseguire il cast dell'oggetto di tipo "System.Configuration.DefaultSection" nel tipo "System.Configuration.AppSettingsSection".
Ecco la soluzione corretta:
System.Configuration.ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = "YourFilePath";
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
Per ASP.NET utilizzare WebConfigurationManager:
var config = WebConfigurationManager.OpenWebConfiguration("~/Sites/" + requestDomain + "/");
(..)
config.AppSettings.Settings["xxxx"].Value;
Utilizza l'elaborazione XML:
var appPath = AppDomain.CurrentDomain.BaseDirectory;
var configPath = Path.Combine(appPath, baseFileName);;
var root = XElement.Load(configPath);
// can call root.Elements(...)
Questo dovrebbe fare al caso tuo:
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", "newAppConfig.config);
Fonte : https://www.codeproject.com/Articles/616065/Perché-Where-and-How-of-NET-Configuration-Files