Nous avons plusieurs projets .NET où nous stockons certains paramètres dans des fichiers de configuration. Maintenant, chaque développeur aura ses propres fichiers de configuration qui diffèrent un peu (différentes chaînes de connexion pour se connecter à la base de données locale, différents points de terminaison WCF, etc.)
Pour le moment, nous avons tendance à consulter les fichiers app/web.config et à les modifier en fonction de nos besoins. Cela conduit à de nombreux problèmes car de temps en temps, quelqu'un vérifiera ses propres paramètres ou perdra la configuration personnalisée lors de l'obtention de la dernière version de tfs.
Ma question est: comment gérez-vous des situations comme celle-ci? Ou vous n'avez pas du tout ce problème?
Nous utilisons un système qui combine plusieurs des réponses existantes sur cette page, plus s'appuie sur cette suggestion de Scott Hanselman .
En bref, ce que nous avons fait était d'avoir un app.config/web.config commun, et d'avoir la plupart des paramètres spécifiques dans des fichiers individuels, comme suggéré par d'autres réponses ici. par exemple. pour nos paramètres SMTP, le fichier app.config contient
<system.net>
<mailSettings>
<smtp configSource="config\smtp.config" />
</mailSettings>
</system.net>
Ce fichier est en contrôle de code source. Cependant, les fichiers individuels, comme celui-ci, ne sont pas:
<?xml version="1.0" encoding="utf-8" ?>
<smtp deliveryMethod="Network">
<network Host="127.0.0.1" port="25" defaultCredentials="false" password="" userName ="" />
</smtp>
Ce n'est pas tout à fait là où l'histoire se termine cependant. Qu'en est-il des nouveaux développeurs ou d'une nouvelle installation source? La majeure partie de la configuration n'est plus dans le contrôle de code source, et il est difficile de créer manuellement tous les fichiers .config dont ils ont besoin. Je préfère avoir une source qui compilera au moins dès la sortie de la boîte.
Par conséquent, nous gardons une version des fichiers .config dans le contrôle de code source, nommée . Config.default . Un nouvel arbre source ressemble donc à ceci:
Pourtant, pas vraiment utile au développeur, car pour Visual Studio, ce ne sont que des fichiers texte sans signification. D'où le fichier batch, copy_default_config.bat
, s'occupe de créer un ensemble initial de fichiers .config à partir des fichiers .config.default:
@echo off
@REM Makes copies of all .default files without the .default extension, only if it doesn't already exist. Does the same recursively through all child folders.
for /r %%f in (*.default) do (
if not exist "%%~pnf" (echo Copying %%~pnf.default to %%~pnf & copy "%%f" "%%~pnf" /y)
)
echo Done.
Le script est réexécutable en toute sécurité, en ce sens que les développeurs qui ont déjà leurs fichiers .config ne les auront pas écrasés. Par conséquent, on pourrait éventuellement exécuter ce fichier de commandes comme un événement de pré-génération. Les valeurs dans les fichiers .default peuvent ne pas être exactement correctes pour une nouvelle installation, mais elles constituent un point de départ raisonnable.
En fin de compte, chaque développeur se retrouve avec un dossier de fichiers de configuration qui ressemble à ceci:
Cela peut sembler un peu compliqué, mais c'est certainement préférable aux tracas des développeurs qui marchent les uns sur les autres.
Dans votre Web.config, utilisez la source d'autres fichiers
<configuration>
<connectionStrings configSource="ConnectionStrings.config" />
...
</configuration>
Gardez le web.config dans le contrôle de version et ne le faites pas pour ConnectionStrings.config. Maintenant, tous les développeurs ont un fichier pour la chaîne de connexion.
Vous pouvez le faire pour tous les paramètres qui dépendent localement.
Voici une solution pour les fichiers web.config et Visual Studio 2010:
1) Modifiez manuellement le fichier .csproj de votre application Web pour ajouter un AfterBuild
Cible comme ceci:
<Project>
...
<Target Name="AfterBuild">
<Copy SourceFiles="web.config" DestinationFiles="obj\$(Configuration)\tempweb.config" />
<TransformXml Source="obj\$(Configuration)\tempweb.config"
Transform="web.$(USERNAME).config"
Destination="obj\$(Configuration)\tempweb2.config" />
<ReadLinesFromFile File="obj\$(Configuration)\tempweb2.config"><Output TaskParameter="Lines" ItemName="TransformedWebConfig"/></ReadLinesFromFile>
<ReadLinesFromFile File="web.config"><Output TaskParameter="Lines" ItemName="UnTransformedWebConfig"/></ReadLinesFromFile>
<Copy Condition=" @(UnTransformedWebConfig) != @(TransformedWebConfig) " SourceFiles="obj\$(Configuration)\tempweb2.config" DestinationFiles="web.config" OverwriteReadOnlyFiles="True" />
</Target>
</Project>
Cette cible transformera le fichier Web.config correspondant au développeur actuel connecté - d'où la variable $(USERNAME)
-, avec le fichier correspondant créé en 1). Il ne remplacera le Web.config local que si le contenu a changé (pour éviter un redémarrage) à chaque génération, même si le Web.config local est contrôlé par la source, c'est pourquoi le OverwriteReadOnlyFiles
est défini sur True. Ce point est en fait défendable.
2) Créez un fichier nommé Web.[developer windows login].config
Pour chaque développeur du projet. (par exemple, dans les captures d'écran suivantes, j'ai deux développeurs nommés smo et smo2):
Ces fichiers (1 par développeur) peuvent/doivent être contrôlés par la source. Ils ne doivent pas être marqués comme dépendants du Web.config principal car nous voulons pouvoir les extraire individuellement.
Chacun de ces fichiers représente une transformation à appliquer au fichier Web.Config principal. La syntaxe de transformation est décrite ici: Web.config Syntaxe de transformation pour le déploiement de projet d'application Web . Nous réutilisons cette tâche de transformation de fichiers Xml sympa qui est prête à l'emploi avec Visual Studio. Le but de cette tâche est de fusionner les éléments et attributs Xml au lieu de remplacer le fichier entier.
Par exemple, voici un exemple web.[dev login].config
Qui modifie une chaîne de connexion nommée 'MyDB', quel que soit le reste du fichier Web.config:
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.Microsoft.com/XML-Document-Transform">
<connectionStrings>
<add name="MyDB"
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
</connectionStrings>
</configuration>
Maintenant, cette solution n'est pas parfaite car:
Mais au moins, vous n'avez qu'à maintenir un web.config principal unique plus un fichier de transformation par développeur.
Une approche similaire pourrait être adoptée pour les fichiers App.config (pas Web) mais je n'ai pas développé davantage.
Nous utilisons machine.config pour éviter d'avoir des différences dans web.config entre les environnements.
Nous avons le même problème et ce que nous faisons est
Que diriez-vous d'ignorer le fichier pour qu'il ne soit jamais enregistré? J'ai rencontré un problème similaire et j'ai ajouté web.config à la liste des ignorés dans Subversion.
Dans TFS cependant, c'est un peu plus difficile, voir ce post sur la façon de le faire.
Une façon de faire face est d'avoir un système à jetons et d'utiliser un script rake pour changer les valeurs.
Une méthode plus rudimentaire pourrait être d'avoir un lien vers un fichier AppSettings.config pour tous les AppSettings dans votre web.config (similaire avec les connexions), c'est-à-dire.
<appSettings configSource="_configs/AppSettings.config" />
Ensuite, ayez un dossier avec chacun de vos développeurs ont une version dans un sous-dossier (c'est-à-dire/_configs/dave /). Ensuite, lorsqu'un développeur travaille sur son propre code, il copie du sous-dossier à la racine du dossier lié.
Vous devrez vous assurer de communiquer les modifications apportées à ces fichiers (sauf si vous effectuez une tokenise). Si vous conservez le fichier AppSettings.config hors du contrôle de source et que vous archivez uniquement les dossiers individuels des développeurs (tous), ils seront obligés de copier le bon.
Je préfère la tokenisation mais peut être plus difficile à mettre en place si cela ne vise qu'à être une solution rapide.
Ignorez les fichiers et disposez d'un Commom_Web.Config et Common_App.Config. Utiliser un serveur de build d'intégration continue avec des tâches de build qui renomment ces deux noms normaux afin que le serveur de build puisse faire son travail.