Fichiers app.config / web.config spécifiques aux développeurs dans Visual Studio

93

Nous avons plusieurs projets .NET dans lesquels nous stockons certains paramètres dans des fichiers de configuration.

Désormais, chaque développeur aura ses propres fichiers de configuration qui diffèrent un peu (différentes chaînes de connexion pour se connecter aux bases de données locales, différents points de terminaison WCF , etc.)

Pour le moment, nous avons tendance à extraire 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érifie ses propres paramètres ou perd sa configuration personnalisée lors de l'obtention de la dernière version de TFS .

Comment gérez-vous des situations comme celle-ci? Ou n'avez-vous pas du tout ce problème?

twarz01
la source
10
Je vote pour la réouverture, car c'est un problème courant pour les développeurs de studio visuel et implique directement les outils utilisés par les développeurs. (d'où les votes)
Christian Gollhardt
D'accord, il s'agit d'un problème persistant car la taille de notre équipe a augmenté et diverses tentatives de résolution ont été insatisfaisantes.
DiskJunky

Réponses:

66

Nous utilisons un système qui combine plusieurs des réponses existantes sur cette page, en plus de s'inspirer de cette suggestion de Scott Hanselman .

En bref, ce que nous avons fait, c'est 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, l'app.config contient

<system.net>
  <mailSettings>
    <smtp configSource="config\smtp.config" />
  </mailSettings>
</system.net>

Ce fichier est sous 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à que l'histoire se termine. Qu'en est-il des nouveaux développeurs ou d'une nouvelle installation source? La majeure partie de la configuration n'est plus sous 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 des sources qui seront au moins compilées dès la sortie de la boîte.

Par conséquent, nous conservons une version des fichiers .config dans le contrôle de code source, nommée .config.default files. Un arbre source frais ressemble donc à ceci:

texte alternatif

Pourtant, cela ne sert vraiment à rien pour le développeur, car pour Visual Studio, ce ne sont que des fichiers texte sans signification. Par conséquent, le fichier batch copy_default_config.bat,, se charge 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 peut être réexécuté en toute sécurité, en ce sens que les développeurs qui ont déjà leurs fichiers .config ne les verront pas écrasés. Par conséquent, il est possible d'exécuter ce fichier de commandes en tant qu'événement de pré-construction. Les valeurs des 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:

texte alternatif

Cela peut sembler un peu compliqué, mais c'est certainement préférable aux tracas des développeurs qui se marchent sur les pieds.

Gavin
la source
Pourquoi ne pas avoir directement le .config principal dans le référentiel mais pas les individuels?
graffic
6
Quelle douleur, nous avons besoin d'une meilleure solution pour cela. J'avais mis en place une méthode similaire et j'en ai eu assez qu'elle soit si fragile et qu'elle ait encore besoin d'explications pour les nouveaux développeurs.
jpierson
@Gavin, j'obtiens une erreur si j'essaie d'exécuter le fichier bat que vous avez décrit: '∩╗┐ @ echo' n'est pas reconnu comme une commande interne ou externe, un programme utilisable ou un fichier de commandes.
Austin
2
@Austin, vous semblez avoir des déchets non imprimables avant le '@echo', dont une partie est possible la marque d'ordre d'octet Unicode? Peut-être que quelque chose s'est mal passé dans le copier / coller, ou le fichier de commandes est enregistré dans un encodage qui ne peut pas être lu correctement.
Gavin
21

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. Désormais, 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 du local.

Filipe Pinheiro
la source
1
Cela a bien fonctionné pour moi. Voir aussi: davidgiard.com/2012/05/25/… Le fichier ConnectionStrings.config doit se trouver dans le même dossier que l'application ou la configuration Web. En outre, vous devez modifier ses propriétés en «copier si plus récent» pour la sortie. Et le fichier ConnectionStrings.config a besoin de la section complète avec les éléments d'ouverture et de fermeture. Vous devez également définir le contrôle de version pour ignorer le fichier afin que chacun soit spécifique à l'utilisateur.
Jeffrey Roughgarden
1
J'ai utilisé l'option <appSettings file = ".."> car je devais fusionner les paramètres
Spikolynn
1
@JeffreyRoughgarden Si vous incluez le fichier ConnectionStrings.config dans l'Explorateur de solutions, le fichier ne doit-il pas nécessairement exister sur le système de fichiers? Et si c'est le cas, cela signifie que vous l'avez archivé dans le contrôle de code source. Quel est le problème initial dont nous essayions de nous éloigner.
Jez
20

Voici une solution pour les fichiers web.config et Visual Studio 2010:

1) Modifiez manuellement le fichier .csproj de votre application Web pour ajouter une AfterBuildcible comme celle-ci:

  <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 $(USERNAME)variable -, avec le fichier correspondant créé en 1). Il remplacera le Web.config local uniquement si le contenu a changé (pour éviter le redémarrage) à chaque build, même si le Web.config local est contrôlé par la source, c'est pourquoi le OverwriteReadOnlyFilesest défini sur True. Ce point est en fait discutable.

2) Créez un fichier nommé Web.[developer windows login].configpour chaque développeur du projet. (par exemple, dans les captures d'écran suivantes, j'ai deux développeurs nommés smo et smo2):

entrez la description de l'image ici

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 fichier Web.config principal car nous voulons pouvoir les extraire individuellement.

Chacun de ce fichier représente une transformation à appliquer au fichier Web.Config principal. La syntaxe de transformation est décrite ici: Syntaxe de transformation Web.config pour le déploiement de projet d'application Web . Nous réutilisons cette tâche de transformation de fichier Xml géniale qui est prête à l'emploi avec Visual Studio. Le but de cette tâche est de fusionner des éléments et des attributs XML au lieu d'écraser le fichier entier.

Par exemple, voici un exemple web.[dev login].configqui 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>

Or, cette solution n'est pas parfaite car:

  • après la construction, les développeurs peuvent avoir un Web.Config différent localement que dans le système de contrôle de source
  • ils peuvent avoir à forcer l'écriture locale lors de l'obtention d'un nouveau Web.Config à partir du système de contrôle de source
  • les développeurs ne doivent pas extraire / dans le web.config principal. Il devrait être réservé à quelques personnes.

Mais au moins, vous n'avez qu'à gérer un fichier web.config principal unique plus un fichier de transformation par développeur.

Une approche similaire pourrait être adoptée pour les fichiers App.config (et non Web), mais je n'ai pas développé davantage.

Simon Mourier
la source
J'ai renommé mon Web.config en Web.base.config, créé un nouveau fichier Web.config, puis changé de <Copy SourceFiles = "web.config"> en <Copy SourceFiles = "web.base.config" à l'étape 1. En faisant cela, je peux avoir un web.config local qui peut être ignoré dans le contrôle de code source.
S.Baggy
Ce n'est toujours pas idéal mais je le préfère à l'autre solution
JMK
Pensez-vous qu'il est possible d'utiliser un web.default.configquand web.$(USERNAME).confign'existe pas? Merci au passage pour cette excellente réponse.
Christian Gollhardt
2

Nous utilisons machine.config pour éviter d'avoir des différences dans web.config entre les environnements.

Darin Dimitrov
la source
14
préfère éviter d'avoir à changer de machine.config
twarz01
0

Pourquoi ne pas ignorer le fichier pour qu'il ne soit jamais archivé? 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, consultez cet article pour savoir comment le faire.

Marko
la source
0

Une façon de faire face est d'avoir un système tokenisé 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) ie

<appSettings configSource="_configs/AppSettings.config" />

Ensuite, ayez un dossier avec chacun de vos développeurs avoir une version dans un sous-dossier (ie / _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 un jeton). Si vous gardez le fichier AppSettings.config hors du contrôle de code source et archivez uniquement les dossiers individuels des développeurs (tous), ils seront obligés de copier le bon.

Je préfère la tokenisation, mais cela peut être plus difficile à démarrer si cela est uniquement destiné à être une solution rapide.

ArtificielOr
la source
0

Ignorez les fichiers et disposez d'un Commom_Web.Config et Common_App.Config. Utilisation d'un serveur de build d'intégration continue avec des tâches de build qui renomme ces deux en noms normaux afin que le serveur de build puisse faire son travail.

Arthis
la source
cela doit être fait sur les machines de développement, avant de passer au serveur de construction
twarz01
Non, ce changement de nom devrait se produire sur le serveur de construction. Les fichiers de configuration courants étant stockés sur la subversion, ils sont indépendants d'un développeur spécifique. Alors que chaque développeur exécute ses fichiers de configuration personnels pour les développer sur sa machine, et ne se soucie pas de le soumettre car il ne fait pas partie de la subversion.
Arthis
Ce que cela ne prend pas en charge, ce sont les développeurs qui déboguent l'application. La racine web.configdu dossier source est utilisée lors du débogage. Si vous, par exemple, ajouté web.configà .gitignoreet non utilisateurs tenus de copier Commom_Web.Configà web.configet de le modifier à leur fantaisie, vous faites partie du chemin. Mais ensuite, lorsque vous avez besoin d'éditer quelque chose qui est le même sur toutes les machines du développeur, comme la system.web/compilationsection ou le particulier appSettingsqui devrait être le même partout, ce schéma s'effondre.
binki
0

Nous avons le même problème et ce que nous faisons est

  • Archivez le web.config avec les valeurs de testerver / production
  • Le développeur accède à l'explorateur Windows et change le mode lecture seule du fichier
  • Modifiez la configuration en fonction de leur environnement.
  • L'enregistrement dans le fichier web.config se produit uniquement lorsque les valeurs de déploiement changent ou qu'une entrée de configuration est ajoutée ou supprimée.
  • Cela nécessite une bonne quantité de commentaires pour chaque entrée de configuration car il doit être modifié par chaque développeur
Joy George Kunjikkuru
la source
1
Cela peut mieux fonctionner dans les magasins où le contrôle de code source que vous utilisez définit les champs en lecture seule par défaut, mais pour d'autres utilisant Subversion, cela peut ne pas fonctionner aussi bien. Nous pourrions définir des autorisations de lecture seule dans le référentiel pour l'empêcher d'être validé, mais cela devrait être défini sur chaque fichier de configuration pour chaque branche.
jpierson
Pour ceux d'entre nous qui n'utilisent pas quelque chose comme TFS, il n'est pas évident de savoir comment cette solution pourrait fonctionner. Pourriez-vous donner un peu plus de contexte? De plus, cela n'oblige-t-il pas les développeurs à faire attention et à ne pas extraire accidentellement le fichier?
binki
-1

En supposant que vous utilisez Visual Studio, pourquoi n'utilisez-vous pas différentes configurations de solution? Par exemple: vous pouvez avoir une configuration Debug qui utilise Web.config.debug et une configuration Release qui utilise Web.config.release. Web.config.debug devrait avoir quelque chose comme

<appSettings file="C:/Standard_Path_To_Configs/Standard_Name_For_Config.config"> 

avec le fichier Standard_Name_For_Config.config qui récupère tous les paramètres personnels du développeur, tandis que Web.config.release a toujours les paramètres de production. Vous pouvez stocker les configurations par défaut dans un dossier contrôlé par la source et faire en sorte qu'un nouvel utilisateur les prenne à partir de là.


la source
Ensuite, chaque utilisateur individuel qui contribuerait au projet devrait avoir sa propre configuration de construction. Cela ne semble pas à l'échelle et ne soutient pas les projets qui acceptent des contributions.
binki