Verwenden von ConfigurationManager zum Laden der Konfiguration von einem beliebigen Speicherort

124

Ich entwickle eine Datenzugriffskomponente, die auf einer Website verwendet wird, die eine Mischung aus klassischen ASP- und ASP.NET-Seiten enthält, und eine gute Möglichkeit zum Verwalten der Konfigurationseinstellungen benötigt.

Ich möchte eine benutzerdefinierte Version verwenden ConfigurationSection, und für die ASP.NET-Seiten funktioniert dies hervorragend. Wenn die Komponente jedoch über COM-Interop von einer klassischen ASP-Seite aufgerufen wird, wird sie nicht im Kontext einer ASP.NET-Anforderung ausgeführt und kennt daher web.config nicht.

Gibt es eine Möglichkeit, ConfigurationManagerdie Konfiguration nur von einem beliebigen Pfad zu laden (z. B. ..\web.configwenn sich meine Assembly im /binOrdner befindet)? Wenn es dann denke ich meine Komponente kann , wenn der Standard das zurückgreifen ConfigurationManager.GetSectionkehrt nullfür meinen benutzerdefinierten Abschnitt.

Alle anderen Ansätze hierfür wären willkommen!

Mike Powell
quelle

Antworten:

124

Versuche dies:

System.Configuration.ConfigurationFileMap fileMap = new ConfigurationFileMap(strConfigPath); //Path to your config file
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
Ishmaeel
quelle
Wie kann ich programmgesteuert den strConfigPath- Wert für meine ASP.NET WebForms- Anwendung abrufen , die in sub.domain.com/virtualDir2 gehostet wird, und den Pfad C: \ Portals \ App1 \ v2 und die Konfigurationsdatei in C: \ Portals \ App1 \ v2 \ web.config ?
Kiquenet
1
@Kiquenet: Der Punkt der Frage ist, dass strConfigPath ein beliebiger Ort ist. Mit anderen Worten, Sie entscheiden, wie der Pfad lautet, anstatt sich auf das Framework zu verlassen, um zu versuchen, eine Konfigurationsdatei von ihrem herkömmlichen Speicherort zu laden. Ich würde davon ausgehen, dass Server.MapPath Ihnen den absoluten Speicherort für alle Dateien in Ihrer Lösung angibt .
Ishmaeel
1
Vielleichtvar config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~/web.config");
Kiquenet
@ Kiquenet Auf jeden Fall.
Ucho
66

Eine andere Lösung besteht darin, den Standardpfad der Umgebungskonfigurationsdatei zu überschreiben.

Ich finde es die beste Lösung für das Laden von Konfigurationsdateien mit nicht trivialen Pfaden, insbesondere die beste Möglichkeit, Konfigurationsdateien an DLL anzuhängen.

AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", <Full_Path_To_The_Configuration_File>);

Beispiel:

AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", @"C:\Shared\app.config");

Weitere Details finden Sie in diesem Blog .

Darüber hinaus bietet diese andere Antwort eine hervorragende Lösung mit Code zum Aktualisieren der App-Konfiguration und einem IDisposableObjekt zum Zurücksetzen auf den ursprünglichen Zustand. Mit dieser Lösung können Sie den Umfang der temporären App-Konfiguration beibehalten:

using(AppConfig.Change(tempFileName))
{
    // tempFileName is used for the app config during this context
}
Saturn Technologies
quelle
1
Dies funktioniert auch zum Laden von web.config-Dateien. Ich verwende es, um eine web.config anstelle von app.config für eine aufgabenbezogene Konsolen-App zu laden. ;)
James Wilkins
1
Dies (und die anderen Antworten hier) funktioniert bei mir nicht. Ich hatte den Code in der program.cs - Funktion hinzugefügt: Main (). Meine Konfiguration enthält eine Assemblyversion-Umleitung (siehe stackoverflow.com/questions/30165393/… ), die Umleitung wirkt sich jedoch nicht aus, wenn die Konfiguration manuell geändert wird.
Vortex852456
1
Haben Sie "APP_CONFIG_FILE" verwendet?
Saturn Technologies
40

Die Antwort von Ishmaeel funktioniert im Allgemeinen, ich habe jedoch ein Problem festgestellt: Die Verwendung OpenMappedMachineConfigurationscheint Ihre geerbten Abschnittsgruppen von machine.config zu verlieren. Dies bedeutet, dass Sie auf Ihre eigenen benutzerdefinierten Abschnitte zugreifen können (was alles ist, was das OP wünscht), jedoch nicht auf die normalen Systemabschnitte. Zum Beispiel funktioniert dieser Code nicht:

ConfigurationFileMap fileMap = new ConfigurationFileMap(strConfigPath);
Configuration configuration = ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
MailSettingsSectionGroup thisMail = configuration.GetSectionGroup("system.net/mailSettings") as MailSettingsSectionGroup;  // returns null

Wenn Sie eine Uhr auf die stellen configuration.SectionGroups, werden Sie feststellen, dass system.net nicht als SectionGroup registriert ist und daher über die normalen Kanäle so gut wie nicht zugänglich ist.

Es gibt zwei Möglichkeiten, dies zu umgehen. Die erste, die mir nicht gefällt, besteht darin, die Systemabschnittsgruppen erneut zu implementieren, indem Sie sie aus machine.config in Ihre eigene web.config kopieren, z

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

Ich bin nicht sicher, ob die Webanwendung selbst danach korrekt ausgeführt wird, aber Sie können korrekt auf die sectionGroups zugreifen.

Die zweite Lösung besteht stattdessen darin, Ihre web.config als EXE-Konfiguration zu öffnen, die wahrscheinlich ohnehin näher an der beabsichtigten Funktion liegt:

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!

Ich gehe davon aus, dass keine der hier gegebenen Antworten, weder meine noch die von Ishmaeel, diese Funktionen so verwenden, wie es die .NET-Designer beabsichtigt haben. Aber das scheint für mich zu funktionieren.

Gavin
quelle
1
Sie können für denselben Zweck auch die Überladung ConfigurationManager.OpenExeConfiguration (String) verwenden. Siehe: codeproject.com/KB/dotnet/mysteriesofconfiguration3.aspx#t2_1
Ohad Schneider
10

Zusätzlich zu Ishmaeels Antwort gibt die Methode OpenMappedMachineConfiguration()immer ein ConfigurationObjekt zurück. Um zu überprüfen, ob es geladen wurde, sollten Sie die HasFileEigenschaft überprüfen, bei der true bedeutet, dass es aus einer Datei stammt.

Joseph Daigle
quelle
9

Die akzeptierte Antwort ist falsch !!

Beim Zugriff auf die AppSettings-Eigenschaft wird die folgende Ausnahme ausgelöst:

Objekt vom Typ 'System.Configuration.DefaultSection' kann nicht in Typ 'System.Configuration.AppSettingsSection' umgewandelt werden.

Hier ist die richtige Lösung:

System.Configuration.ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = "YourFilePath";
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
Jacob
quelle
1
Ja, das ist definitiv die richtige Antwort! Vielen Dank für Ihre Antwort.
Fabio Milheiro
Ich denke, System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration ist noch korrekter, aber für .NET Core nicht verfügbar. In diesem Fall scheint diese Antwort die Arbeit zu erledigen.
Risord
4

Ich habe die Konfigurationswerte für Word Hosted .nET Compoent wie folgt bereitgestellt.

Eine .NET-Klassenbibliothekskomponente, die in MS Word aufgerufen / gehostet wird. Um meiner Komponente Konfigurationswerte bereitzustellen, habe ich winword.exe.config im Ordner C: \ Programme \ Microsoft Office \ OFFICE11 erstellt. Sie sollten in der Lage sein, Konfigurationswerte wie in herkömmlichem .NET zu lesen.

string sMsg = System.Configuration.ConfigurationManager.AppSettings["WSURL"];
Iftikhar Ali
quelle
1

Verwenden Sie für ASP.NET WebConfigurationManager:

var config = WebConfigurationManager.OpenWebConfiguration("~/Sites/" + requestDomain + "/");
(..)
config.AppSettings.Settings["xxxx"].Value;
Javier Cañon
quelle
0

Verwenden Sie die XML-Verarbeitung:

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

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