Używanie ConfigurationManager do załadowania konfiguracji z dowolnej lokalizacji

124

Tworzę komponent dostępu do danych, który będzie używany w witrynie sieci Web zawierającej połączenie klasycznych stron ASP i ASP.NET i potrzebuję dobrego sposobu zarządzania ustawieniami konfiguracji.

Chciałbym użyć niestandardowego ConfigurationSection, a dla stron ASP.NET działa to świetnie. Ale gdy składnik jest wywoływany za pośrednictwem współdziałania COM z klasycznej strony ASP, składnik nie działa w kontekście żądania ASP.NET i dlatego nie ma wiedzy o pliku web.config.

Czy istnieje sposób, aby po ConfigurationManagerprostu załadować konfigurację z dowolnej ścieżki (np. ..\web.configJeśli mój zestaw znajduje się w /binfolderze)? Jeśli tak, myślę, że mój komponent może wrócić do tego, jeśli wartość domyślna ConfigurationManager.GetSectionwróci nulldo mojej sekcji niestandardowej.

Wszelkie inne podejście do tego byłoby mile widziane!

Mike Powell
źródło
2
Zobacz stackoverflow.com/questions/3912727/…
Ohad Schneider,

Odpowiedzi:

124

Spróbuj tego:

System.Configuration.ConfigurationFileMap fileMap = new ConfigurationFileMap(strConfigPath); //Path to your config file
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
Ishmaeel
źródło
Jak programowo uzyskać wartość strConfigPath dla mojej aplikacji ASP.NET WebForms hostowanej w sub.domain.com/virtualDir2 i ścieżce C: \ Portals \ App1 \ v2 oraz plik konfiguracyjny w C: \ Portals \ App1 \ v2 \ web.config ?
Kiquenet,
1
@Kiquenet: Chodzi o to, że strConfigPath to dowolna lokalizacja. Innymi słowy, ty decydujesz, jaka jest ścieżka, zamiast polegać na frameworku, aby spróbować załadować plik konfiguracyjny z jego konwencjonalnej lokalizacji. Zakładam, że Server.MapPath poda bezwzględną lokalizację wszystkich plików w rozwiązaniu.
Ishmaeel
1
Możevar config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~/web.config");
Kiquenet,
@Kiquenet Zdecydowanie.
Ucho
66

Innym rozwiązaniem jest zastąpienie domyślnej ścieżki pliku konfiguracji środowiska.

Uważam, że jest to najlepsze rozwiązanie do ładowania pliku konfiguracyjnego z nietrywialną ścieżką, w szczególności najlepszy sposób na dołączenie pliku konfiguracyjnego do dll.

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

Przykład:

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

Więcej szczegółów można znaleźć na tym blogu .

Ponadto ta druga odpowiedź ma doskonałe rozwiązanie, wraz z kodem do odświeżenia konfiguracji aplikacji i IDisposableobiektem do zresetowania jej z powrotem do pierwotnego stanu. Dzięki temu rozwiązaniu możesz zachować zakres tymczasowej konfiguracji aplikacji:

using(AppConfig.Change(tempFileName))
{
    // tempFileName is used for the app config during this context
}
Saturn Technologies
źródło
1
Działa to również w przypadku ładowania plików web.config. Używam go do załadowania pliku web.config zamiast app.config dla aplikacji konsoli związanej z zadaniami. ;)
James Wilkins
1
To (i inne odpowiedzi tutaj) nie działa dla mnie. Dodałem kod w program.cs - funkcja: Main (). Moja konfiguracja zawiera przekierowanie wersji zestawu (patrz stackoverflow.com/questions/30165393/ ... ), ale przekierowanie nie ma wpływu na ręczną zmianę konfiguracji.
Vortex852456
1
Czy użyłeś „APP_CONFIG_FILE”?
Saturn Technologies
40

Odpowiedź Ishmaeela generalnie działa, jednak znalazłem jeden problem, który polega na tym, że używanie OpenMappedMachineConfigurationwydaje się powodować utratę dziedziczonych grup sekcji z pliku machine.config. Oznacza to, że możesz uzyskać dostęp do własnych sekcji niestandardowych (czyli wszystkich potrzebnych OP), ale nie do normalnych sekcji systemu. Na przykład ten kod nie zadziała:

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

Zasadniczo, jeśli umieścisz zegarek na configuration.SectionGroups , zobaczysz, że system.net nie jest zarejestrowany jako grupa SectionGroup, więc jest prawie niedostępny za pośrednictwem normalnych kanałów.

Znalazłem dwa sposoby obejścia tego problemu. Pierwszym, co mi się nie podoba, jest ponowne zaimplementowanie systemowych grup sekcji poprzez skopiowanie ich z pliku machine.config do własnego web.config np.

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

Nie jestem pewien, czy po tym aplikacja internetowa będzie działać poprawnie, ale możesz uzyskać poprawny dostęp do sekcjiGrupy.

Drugim rozwiązaniem jest zamiast tego otwarcie pliku web.config jako konfiguracji EXE, która i tak prawdopodobnie jest bliższa zamierzonej funkcji:

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!

Ośmielam się twierdzić, że żadna z udzielonych tutaj odpowiedzi, ani moja, ani Ishmaeel, nie wykorzystują tych funkcji tak, jak zamierzali projektanci .NET. Ale to wydaje się działać dla mnie.

Gavin
źródło
1
W tym samym celu można również użyć przeciążenia ConfigurationManager.OpenExeConfiguration (String). Zobacz: codeproject.com/KB/dotnet/mysteriesofconfiguration3.aspx#t2_1
Ohad Schneider,
10

Oprócz odpowiedzi Ishmaeela metoda OpenMappedMachineConfiguration()zawsze zwróci Configurationobiekt. Aby więc sprawdzić, czy został załadowany, należy sprawdzić HasFilewłaściwość, gdzie prawda oznacza, że ​​pochodzi z pliku.

Joseph Daigle
źródło
9

Przyjęta odpowiedź jest nieprawidłowa !!

Zgłasza następujący wyjątek podczas uzyskiwania dostępu do właściwości AppSettings:

Nie można rzutować obiektu typu „System.Configuration.DefaultSection” na typ „System.Configuration.AppSettingsSection”.

Oto poprawne rozwiązanie:

System.Configuration.ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = "YourFilePath";
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
Jakub
źródło
1
tak, to zdecydowanie właściwa odpowiedź! Dziękujemy za przesłanie odpowiedzi.
Fabio Milheiro
Myślę, że System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration jest jeszcze bardziej poprawny, ale nie jest dostępny dla .NET Core, więc w tym przypadku ta odpowiedź wydaje się być wykonana.
Risord
4

Podałem wartości konfiguracyjne do Word Hosted .nET Compoent w następujący sposób.

Składnik biblioteki klas .NET wywoływany / hostowany w programie MS Word. Aby zapewnić wartości konfiguracyjne dla mojego komponentu, utworzyłem winword.exe.config w folderze C: \ Program Files \ Microsoft Office \ OFFICE11. Powinieneś być w stanie odczytać wartości konfiguracji, tak jak robisz to w tradycyjnym .NET.

string sMsg = System.Configuration.ConfigurationManager.AppSettings["WSURL"];
Iftikhar Ali
źródło
1

W przypadku ASP.NET użyj WebConfigurationManager:

var config = WebConfigurationManager.OpenWebConfiguration("~/Sites/" + requestDomain + "/");
(..)
config.AppSettings.Settings["xxxx"].Value;
Javier Cañon
źródło
0

Użyj przetwarzania XML:

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

// can call root.Elements(...)
JoelFan
źródło