Uso di ConfigurationManager per caricare la configurazione da una posizione arbitraria


124

Sto sviluppando un componente di accesso ai dati che verrà utilizzato in un sito Web che contiene un mix di classiche pagine ASP e ASP.NET e ho bisogno di un buon modo per gestire le sue impostazioni di configurazione.

Vorrei usare un'usanza personalizzata ConfigurationSectione per le pagine ASP.NET funziona alla grande. Ma quando il componente viene chiamato tramite interoperabilità COM da una pagina ASP classica, il componente non è in esecuzione nel contesto di una richiesta ASP.NET e quindi non ha conoscenza di web.config.

C'è un modo per dire ConfigurationManagera come caricare la configurazione da un percorso arbitrario (ad esempio ..\web.configse il mio assembly è nella /bincartella)? In tal caso, sto pensando che il mio componente possa tornare a quello se il valore predefinito ConfigurationManager.GetSectionritorna nullper la mia sezione personalizzata.

Qualsiasi altro approccio a questo sarebbe il benvenuto!


Risposte:


124

Prova questo:

System.Configuration.ConfigurationFileMap fileMap = new ConfigurationFileMap(strConfigPath); //Path to your config file
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedMachineConfiguration(fileMap);

Come posso ottenere a livello di codice strConfigPath valore per il mio ASP.NET WebForms un'applicazione ospitata in sub.domain.com/virtualDir2 e il percorso C: \ \ v2 \ Portali App1 e configurazione del file in C: \ Portals \ App1 \ v2 \ web.config ?
Kiquenet,

1
@Kiquenet: il punto della domanda è che strConfigPath è una posizione arbitraria . In altre parole, si decide che cosa il percorso è, invece di basarsi sul quadro per cercare di caricare un file di configurazione dalla sua posizione tradizionale. Suppongo Server.MapPath ti darebbe la posizione assoluta per qualsiasi file all'interno della tua soluzione.
Ismaele

1
Forsevar config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~/web.config");
Kiquenet il

@Kiquenet Sicuramente.
Ucho,

66

Un'altra soluzione è quella di sostituire il percorso del file di configurazione dell'ambiente predefinito.

Trovo che sia la soluzione migliore per il caricamento di file di configurazione non banali, in particolare il modo migliore per collegare 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 in questo blog .

Inoltre, questa altra risposta ha una soluzione eccellente, completa di codice per aggiornare la configurazione dell'app e un IDisposableoggetto per ripristinarlo allo stato originale. Con questa soluzione, puoi mantenere l'app temporanea configurata nell'ambito:

using(AppConfig.Change(tempFileName))
{
    // tempFileName is used for the app config during this context
}

1
Questo funziona anche per caricare i file web.config. Lo uso per caricare un web.config invece di app.config per un'app console relativa alle attività. ;)
James Wilkins

1
Questo (e le altre risposte qui) non funziona per me. Avevo aggiunto il codice in program.cs - funzione: Main (). La mia configurazione contiene un reindirizzamento della versione dell'assembly (consultare stackoverflow.com/questions/30165393/… ) ma il reindirizzamento non ha alcun effetto quando la configurazione viene modificata manualmente.
Vortex852456,

1
Hai usato "APP_CONFIG_FILE"?
Saturn Technologies,

40

La risposta di Ishmaeel generalmente funziona, tuttavia ho riscontrato un problema, ovvero che l'utilizzo OpenMappedMachineConfigurationsembra perdere i gruppi di sezioni ereditate da machine.config. Ciò significa che è possibile accedere alle proprie sezioni personalizzate (che è tutto l'OP desiderato), 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 su configuration.SectionGroups, vedrai che system.net non è registrato come SectionGroup, quindi è praticamente inaccessibile tramite i normali canali.

Ci sono due modi in cui ho scoperto di aggirare questo problema. Il primo, che non mi piace, è implementare nuovamente i gruppi di sezioni del sistema copiandoli da machine.config nel proprio 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 la stessa applicazione web funzionerà correttamente dopo quella, ma puoi accedere correttamente alla sezione Gruppi.

La seconda soluzione è invece quella di aprire web.config come configurazione EXE, che comunque è probabilmente più vicino 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!

Non oso dire che nessuna delle risposte fornite qui, né la mia né quella di Ishmaeel, stia piuttosto usando queste funzioni come intendevano i progettisti di .NET. Ma questo sembra funzionare per me.


1
È inoltre possibile utilizzare il sovraccarico ConfigurationManager.OpenExeConfiguration (String) per lo stesso scopo. Vedi: codeproject.com/KB/dotnet/mysteriesofconfiguration3.aspx#t2_1
Ohad Schneider

10

Oltre alla risposta di Ismaele, il metodo OpenMappedMachineConfiguration()restituirà sempre un Configurationoggetto. Quindi per verificare se è stato caricato, è necessario controllare la HasFileproprietà dove true indica che proviene da un file.


9

La risposta accettata è sbagliata !!

Genera la seguente eccezione all'accesso alla proprietà AppSettings:

Impossibile eseguire il cast dell'oggetto di tipo "System.Configuration.DefaultSection" per digitare "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);

1
si, questa è sicuramente la risposta giusta! Grazie per aver pubblicato la tua risposta.
Fabio Milheiro,

Penso che System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration sia ancora più corretto ma non è disponibile per .NET Core, quindi in questo caso sembra che questa risposta funzioni.
Risord,

4

Ho fornito i valori di configurazione al componente .nET ospitato a parola 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 delle configurazioni come fai in .NET tradizionale.

string sMsg = System.Configuration.ConfigurationManager.AppSettings["WSURL"];

1

Per ASP.NET utilizzare WebConfigurationManager:

var config = WebConfigurationManager.OpenWebConfiguration("~/Sites/" + requestDomain + "/");
(..)
config.AppSettings.Settings["xxxx"].Value;

0

Usa elaborazione XML:

var appPath = AppDomain.CurrentDomain.BaseDirectory;
var configPath = Path.Combine(appPath, baseFileName);;
var root = XElement.Load(configPath);

// can call root.Elements(...)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.