Utilisation de ConfigurationManager pour charger la configuration à partir d'un emplacement arbitraire

124

Je développe un composant d'accès aux données qui sera utilisé dans un site Web contenant un mélange de pages ASP et ASP.NET classiques, et j'ai besoin d'un bon moyen de gérer ses paramètres de configuration.

J'aimerais utiliser une personnalisation ConfigurationSection, et pour les pages ASP.NET, cela fonctionne très bien. Mais lorsque le composant est appelé via COM Interop à partir d'une page ASP classique, le composant ne s'exécute pas dans le contexte d'une requête ASP.NET et n'a donc aucune connaissance de web.config.

Existe-t-il un moyen de dire au ConfigurationManagerde charger simplement la configuration à partir d'un chemin arbitraire (par exemple ..\web.configsi mon assembly est dans le /bindossier)? S'il est alors je pense mon composant peut revenir à la valeur par défaut que si les ConfigurationManager.GetSectionrendements nullde ma section personnalisée.

Toute autre approche serait la bienvenue!

Mike Powell
la source

Réponses:

124

Essaye ça:

System.Configuration.ConfigurationFileMap fileMap = new ConfigurationFileMap(strConfigPath); //Path to your config file
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
Ismaël
la source
Comment puis-je obtenir par programme la valeur strConfigPath pour mon application ASP.NET WebForms hébergée dans sub.domain.com/virtualDir2 et le chemin C: \ Portals \ App1 \ v2 et le fichier de configuration dans C: \ Portals \ App1 \ v2 \ web.config ?
Kiquenet
1
@Kiquenet: Le point de la question est que strConfigPath est un emplacement arbitraire . En d'autres termes, vous décidez quel est le chemin, au lieu de vous fier au framework pour essayer de charger un fichier de configuration à partir de son emplacement conventionnel. Je suppose que Server.MapPath vous donnerait l'emplacement absolu de tous les fichiers de votre solution.
Ishmaeel
1
Peutvar config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~/web.config");
Kiquenet
@Kiquenet Certainement.
Ucho le
66

Une autre solution consiste à remplacer le chemin du fichier de configuration d'environnement par défaut.

Je trouve que c'est la meilleure solution pour le chargement de fichier de configuration de chemin non trivial, en particulier la meilleure façon de joindre un fichier de configuration à dll.

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

Exemple:

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

Plus de détails peuvent être trouvés sur ce blog .

De plus, cette autre réponse a une excellente solution, complète avec du code pour actualiser la configuration de l'application et un IDisposableobjet pour la réinitialiser à son état d'origine. Avec cette solution, vous pouvez conserver la configuration de l'application temporaire:

using(AppConfig.Change(tempFileName))
{
    // tempFileName is used for the app config during this context
}
Technologies Saturn
la source
1
Cela fonctionne également pour charger les fichiers web.config. Je l'utilise pour charger un web.config au lieu de app.config pour une application console liée aux tâches. ;)
James Wilkins
1
Cela (et les autres réponses ici) ne fonctionne pas pour moi. J'avais ajouté le code dans le programme.cs - fonction: Main (). Ma configuration contient une redirection de version d'assembly (voir stackoverflow.com/questions/30165393/… ) mais la redirection n'affecte pas le moment où la configuration est modifiée manuellement.
Vortex852456
1
Avez-vous utilisé "APP_CONFIG_FILE"?
Saturn Technologies
40

La réponse d'Ishmaeel fonctionne généralement, mais j'ai trouvé un problème, qui est que l'utilisation OpenMappedMachineConfigurationsemble perdre vos groupes de sections hérités de machine.config. Cela signifie que vous pouvez accéder à vos propres sections personnalisées (ce qui est tout ce que l'OP recherché), mais pas aux sections système normales. Par exemple, ce code ne fonctionnera pas:

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

En gros, si vous mettez une montre sur le configuration.SectionGroups, vous verrez que system.net n'est pas enregistré en tant que SectionGroup, donc il est pratiquement inaccessible via les canaux normaux.

J'ai trouvé deux façons de contourner ce problème. La première, que je n'aime pas, est de réimplémenter les groupes de sections système en les copiant de machine.config dans votre propre web.config, par exemple

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

Je ne suis pas sûr que l'application Web elle-même fonctionnera correctement après cela, mais vous pouvez accéder correctement à la sectionGroups.

La deuxième solution consiste à ouvrir votre web.config en tant que configuration EXE, qui est probablement plus proche de sa fonction prévue de toute façon:

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!

J'ose dire qu'aucune des réponses fournies ici, ni la mienne ni celle d'Ishmaeel, n'utilise tout à fait ces fonctions comme les concepteurs .NET l'ont voulu. Mais cela semble fonctionner pour moi.

Gavin
la source
1
Vous pouvez également utiliser la surcharge ConfigurationManager.OpenExeConfiguration (String) dans le même but. Voir: codeproject.com/KB/dotnet/mysteriesofconfiguration3.aspx#t2_1
Ohad Schneider
10

En plus de la réponse d'Ishmaeel, la méthode OpenMappedMachineConfiguration()retournera toujours un Configurationobjet. Donc, pour vérifier si elle est chargée, vous devez vérifier la HasFilepropriété où true signifie qu'elle provient d'un fichier.

Joseph Daigle
la source
9

La réponse acceptée est fausse !!

Il lève l'exception suivante lors de l'accès à la propriété AppSettings:

Impossible de convertir un objet de type «System.Configuration.DefaultSection» en «System.Configuration.AppSettingsSection».

Voici la bonne solution:

System.Configuration.ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = "YourFilePath";
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
Jacob
la source
1
oui, c'est définitivement la bonne réponse! Merci d'avoir publié votre réponse.
Fabio Milheiro
Je pense que System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration est encore plus correct mais il n'est pas disponible pour .NET Core, donc dans ce cas, cette réponse semble faire le travail.
Risord
4

J'ai fourni les valeurs de configuration à Word .nET Compoent hébergé comme suit.

Un composant de bibliothèque de classes .NET appelé / hébergé dans MS Word. Pour fournir des valeurs de configuration à mon composant, j'ai créé winword.exe.config dans le dossier C: \ Program Files \ Microsoft Office \ OFFICE11. Vous devriez pouvoir lire les valeurs de configuration comme vous le faites dans .NET traditionnel.

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

Pour ASP.NET, utilisez WebConfigurationManager:

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

Utilisez le traitement XML:

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

// can call root.Elements(...)
JoelFan
la source