File app.config / web.config specifici dello sviluppatore in Visual Studio


93

Abbiamo diversi progetti .NET in cui memorizziamo determinate impostazioni nei file di configurazione.

Ora ogni sviluppatore avrà i propri file di configurazione che differiscono leggermente (stringhe di connessione diverse per connettersi a database locali, diversi endpoint WCF , ecc.)

Al momento tendiamo a controllare i file app / web.config e a modificarli per adattarli alle nostre esigenze.

Ciò porta a molti problemi poiché di tanto in tanto qualcuno controllerà le proprie impostazioni o perderà la configurazione personalizzata quando ottiene l'ultima versione da TFS .

Come affronti situazioni come questa? O non hai affatto questo problema?


10
Voto per riaprire, poiché questo è un problema comune per gli sviluppatori di studi visivi e coinvolge direttamente gli strumenti che gli sviluppatori stanno utilizzando. (da qui i voti)
Christian Gollhardt

D'accordo, questo è un problema persistente poiché le dimensioni del nostro team sono aumentate e vari tentativi di risoluzione sono stati insoddisfacenti.
DiskJunky

Risposte:


66

Usiamo un sistema che combina molte delle risposte esistenti in questa pagina, più si ispira a questo suggerimento di Scott Hanselman .

In breve, quello che abbiamo fatto è stato avere un'app.config / web.config comune e avere la maggior parte delle impostazioni specifiche nei singoli file, come suggerito da altre risposte qui. ad esempio, per le nostre impostazioni SMTP, app.config contiene

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

Questo file è nel controllo del codice sorgente. Tuttavia, i singoli file, come questo, non sono:

<?xml version="1.0" encoding="utf-8" ?>
<smtp deliveryMethod="Network">
  <network host="127.0.0.1" port="25" defaultCredentials="false" password="" userName ="" />
</smtp>

Ma non è proprio qui che finisce la storia. E i nuovi sviluppatori o una nuova installazione dei sorgenti? La maggior parte della configurazione non è più nel controllo del codice sorgente ed è un problema creare manualmente tutti i file .config di cui hanno bisogno. Preferisco avere un sorgente che almeno si compili immediatamente.

Pertanto manteniamo una versione dei file .config nel controllo del codice sorgente, denominata file .config.default . Un nuovo albero dei sorgenti appare quindi così:

testo alternativo

Tuttavia, non è davvero utile per lo sviluppatore, poiché per Visual Studio sono solo file di testo privi di significato. Quindi il file batch copy_default_config.bat,, si occupa di creare un set iniziale di file .config dai file .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.

Lo script può essere rieseguito in modo sicuro, in quanto gli sviluppatori che hanno già i propri file .config non li sovrascriveranno. Pertanto, si potrebbe plausibilmente eseguire questo file batch come evento di pre-compilazione. I valori nei file .default potrebbero non essere esattamente corretti per una nuova installazione, ma sono un punto di partenza ragionevole.

In definitiva, ciò con cui ogni sviluppatore finisce è una cartella di file di configurazione che assomiglia a questo:

testo alternativo

Può sembrare un po 'complicato, ma è decisamente preferibile alla seccatura degli sviluppatori che si pestano a vicenda.


Perché non avere direttamente nel repository i file .config principali ma non quelli individuali?
Graffic

6
Che dolore, abbiamo bisogno di una soluzione migliore per questo. Avevo impostato un metodo simile e mi ero stancato di essere così fragile e di dover ancora spiegare ai nuovi sviluppatori.
jpierson

@ Gavin, ricevo un errore se provo a eseguire il file bat che hai delineato: "∩╗┐ @ echo" non è riconosciuto come comando interno o esterno, programma eseguibile o file batch.
Austin

2
@Austin, sembra che tu abbia un po 'di spazzatura non stampabile prima di "@echo", parte del quale è possibile il contrassegno dell'ordine dei byte Unicode? Forse qualcosa è andato storto nel copia / incolla o il file batch è stato salvato in una codifica che non può essere letta correttamente.
Gavin

21

Nel tuo Web.config usa la sorgente da altri file

<configuration>
    <connectionStrings configSource="ConnectionStrings.config" />
...
</configuration>

Mantieni web.config nel controllo della versione e non farlo per ConnectionStrings.config. Ora tutti gli sviluppatori hanno un file per la stringa di connessione.

Puoi farlo per tutte le impostazioni che dipendono dal locale.


1
Questo ha funzionato bene per me. Vedi anche: davidgiard.com/2012/05/25/… Il file ConnectionStrings.config deve essere nella stessa cartella dell'app o della configurazione web. Inoltre, è necessario modificare le sue proprietà in "copia se più recente" per l'output. E il file ConnectionStrings.config richiede la sezione completa con elementi di apertura e chiusura. È inoltre necessario impostare il controllo della versione per ignorare il file in modo che ciascuno sia specifico dell'utente.
Jeffrey Roughgarden

1
Ho utilizzato l'opzione <appSettings file = ".."> poiché dovevo unire le impostazioni
Spikolynn

1
@ JeffreyRoughgarden Se includi il file ConnectionStrings.config in Esplora soluzioni, il file non deve necessariamente esistere in filesysterm? E se lo fa, significa che l'hai controllato nel controllo del codice sorgente. Qual è il problema iniziale da cui stavamo cercando di allontanarci.
Jez

20

Ecco una soluzione per i file web.config e Visual Studio 2010:

1) Modifica manualmente il file .csproj dell'applicazione web per aggiungere un AfterBuildTarget come questo:

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

Questo obiettivo trasformerà il file Web.config corrispondente allo sviluppatore corrente connesso - da qui la $(USERNAME)variabile -, con il file corrispondente creato in 1). Sostituirà il Web.config locale solo se il contenuto è cambiato (per evitare il riavvio) ad ogni build, anche se il Web.config locale è controllato dal codice sorgente, ecco perché OverwriteReadOnlyFilesè impostato su True. Questo punto infatti è discutibile.

2) Crea un file denominato Web.[developer windows login].configper ogni sviluppatore del progetto. (ad esempio negli screenshot seguenti ho due sviluppatori chiamati smo e smo2):

inserisci qui la descrizione dell'immagine

Questi file (1 per sviluppatore) possono / devono essere controllati dal codice sorgente. Non dovrebbero essere contrassegnati come dipendenti dal Web.config principale perché vogliamo essere in grado di controllarli individualmente.

Ciascuno di questo file rappresenta una trasformazione da applicare al file Web.Config principale. La sintassi della trasformazione è descritta qui: Web.config Transformation Syntax for Web Application Project Deployment . Riutilizziamo questa fantastica attività di trasformazione di file Xml che viene fornita immediatamente con Visual Studio. Lo scopo di questa attività è unire elementi e attributi Xml invece di sovrascrivere l'intero file.

Ad esempio, ecco un esempio web.[dev login].configche modifica una stringa di connessione denominata "MyDB", indipendentemente dal resto del file 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>

Ora, questa soluzione non è perfetta perché:

  • dopo la compilazione, gli sviluppatori potrebbero avere un Web.Config diverso a livello locale rispetto al sistema di controllo del codice sorgente
  • potrebbe essere necessario forzare la scrittura locale quando si ottiene un nuovo Web.Config dal sistema di controllo del codice sorgente
  • gli sviluppatori non dovrebbero controllare / nel web.config principale. Dovrebbe essere riservato a poche persone.

Ma almeno, devi solo mantenere un unico web.config principale più un file di trasformazione per sviluppatore.

Un approccio simile potrebbe essere adottato per i file App.config (non web) ma non ho elaborato ulteriormente.


Ho rinominato il mio Web.config in Web.base.config, creato un nuovo file Web.config, quindi cambiato da <Copy SourceFiles = "web.config"> a <Copy SourceFiles = "web.base.config" nel passaggio 1. In questo modo, posso avere un web.config locale che può essere ignorato nel controllo del codice sorgente.
S. Baggy

Questo non è ancora l'ideale, ma lo preferisco all'altra soluzione
JMK

Pensi che sia possibile utilizzare un web.default.configquando web.$(USERNAME).confignon esiste? Grazie a proposito per questa ottima risposta.
Christian Gollhardt

2

Stiamo usando machine.config per evitare differenze in web.config tra gli ambienti.


14
preferirei evitare di dover cambiare machine.config
twarz01

0

Che ne dici di ignorare il file, in modo che non venga mai archiviato? Ho riscontrato un problema simile e ho aggiunto web.config all'elenco delle persone da ignorare in Subversion.

In TFS, però, è un po 'più difficile, guarda questo post su come farlo.


0

Un modo per farcela è avere un sistema tokenizzato e utilizzare uno script rake per modificare i valori.

Un metodo più rudimentale potrebbe essere quello di avere un collegamento a un file AppSettings.config per tutte le AppSettings nel tuo web.config (simile con le connessioni) cioè

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

Quindi crea una cartella con ciascuno dei tuoi sviluppatori e una versione in una sottocartella (ad esempio / _configs / dave /). Quindi, quando uno sviluppatore sta lavorando sul proprio codice, copia dalla sottocartella alla radice della cartella collegata.

Sarà necessario assicurarsi di comunicare le modifiche a questi file (a meno che non si tokenizzino). Se mantieni il file AppSettings.config fuori dal controllo del codice sorgente e controlli solo le singole cartelle degli sviluppatori (tutte), saranno costretti a copiare quella corretta.

Preferisco la tokenizzazione, ma può essere più difficile da installare e funzionare se questo è solo pensato per essere una soluzione rapida.


0

Ignorare i file e avere un Commom_Web.Config e Common_App.Config. Utilizzo di un server di compilazione a integrazione continua con attività di compilazione che rinomina questi due in nomi normali in modo che il server di compilazione possa svolgere il proprio lavoro.


questo deve essere fatto su macchine di sviluppo, prima che vada al server di compilazione
twarz01

No, questa ridenominazione dovrebbe avvenire sul server di compilazione. I file di configurazione comuni archiviati in subversion, sono indipendenti da uno specifico sviluppatore. Considerando che ogni sviluppatore esegue i suoi file di configurazione personali per sviluppare sulla sua macchina, e non si preoccupa di inviarlo perché non fa parte della sovversione.
Arthis

La cosa che questo non supporta è che gli sviluppatori eseguono il debug dell'applicazione. La radice web.confignella cartella di origine viene utilizzata durante il debug. Se, ad esempio, aggiunto web.configalla .gitignoree sia richiesto agli utenti di copiare Commom_Web.Configper web.confige modificarlo per la loro fantasia, è un pezzo di strada ci sei. Ma poi quando è necessario modificare qualcosa che è lo stesso su tutte le macchine dello sviluppatore, come la system.web/compilationsezione o il particolare appSettingsche dovrebbe essere lo stesso ovunque, questo schema va in pezzi.
binki

0

Abbiamo lo stesso problema e quello che stiamo facendo lo è

  • Controlla il web.config con i valori di testserver / production
  • Lo sviluppatore accede a Windows Explorer e modifica la modalità di sola lettura del file
  • Modifica la configurazione per adattarla al loro ambiente.
  • Il check-in in web.config avviene solo quando i valori di distribuzione cambiano o qualsiasi voce di configurazione viene aggiunta o eliminata.
  • Ciò richiede una buona quantità di commenti per ogni voce di configurazione poiché deve essere modificata da ogni sviluppatore

1
Questo potrebbe funzionare meglio nei negozi in cui il controllo del codice sorgente che usi imposta i campi come Sola lettura per impostazione predefinita, ma per altri che usano Subversion potrebbe non funzionare altrettanto. Potremmo impostare permessi di sola lettura nel repository per impedirne il commit, tuttavia ciò dovrebbe essere impostato su ogni file di configurazione per ogni ramo.
jpierson

Per quelli di noi che non usano qualcosa come TFS, non è ovvio come potrebbe funzionare questa soluzione. Potresti dare un po 'più di background? Inoltre, non richiede agli sviluppatori di fare attenzione e di non estrarre accidentalmente il file?
binki

-1

Supponendo che tu stia utilizzando Visual Studio, perché non utilizzi configurazioni di soluzioni diverse? Ad esempio: puoi avere una configurazione di debug che utilizza Web.config.debug e una configurazione di rilascio che utilizza Web.config.release. Web.config.debug dovrebbe avere qualcosa di simile

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

con il file Standard_Name_For_Config.config che raccoglie tutte le impostazioni personali dello sviluppatore, mentre Web.config.release ha sempre le impostazioni di produzione. Puoi memorizzare le configurazioni predefinite in una cartella controllata dal codice sorgente e fare in modo che un nuovo utente le prenda da lì.


Quindi ogni singolo utente che avrebbe mai contribuito al progetto avrebbe bisogno di avere la propria configurazione di build. Questo non sembra scalare e non supporta progetti che accettano contributi.
binki
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.