Visual Studio中开发人员特定的app.config / web.config文件
我们有几个.NET项目,我们将某些设置存储在configuration文件中。 现在每个开发人员都有自己的configuration文件,这些configuration文件有点不同(不同的连接string连接到本地数据库,不同的WCF端点等)
目前我们倾向于检查app / web.config文件并修改它们以适应我们的需要。 这会导致很多问题,因为有时候会有人在从tfs获取最新版本时检查自己的设置或者自定义configuration。
我的问题是:你如何处理这样的情况? 或者你根本没有这个问题?
我们使用一个系统,结合了这个页面上现有的几个答案,再加上Scott Hanselman的这个build议 。
简而言之,我们所做的就是拥有一个通用的app.config / web.config,并在个别文件中拥有大部分的特定设置,正如其他答案所build议的。 例如对于我们的SMTP设置,app.config包含
<system.net> <mailSettings> <smtp configSource="config\smtp.config" /> </mailSettings> </system.net>
该文件在源代码pipe理中。 但是,像这样的单个文件不是:
<?xml version="1.0" encoding="utf-8" ?> <smtp deliveryMethod="Network"> <network host="127.0.0.1" port="25" defaultCredentials="false" password="" userName ="" /> </smtp>
这不是故事结束的地方。 那么新的开发者或新鲜的源代码安装呢? 大部分configuration已经不在源代码pipe理中,手动构build所需的所有.config文件是一件很痛苦的事情。 我更喜欢有源代码,至less可以立即编译。
因此,我们在源代码pipe理中保留了一个名为.config.default文件的.config文件。 因此,新鲜的源代码树如下所示:
尽pipe如此,开发人员并没有什么用处,因为对于Visual Studio他们只是没有意义的文本文件。 因此,batch filecopy_default_config.bat
负责从.config.default文件创build一组.config文件:
@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.
该脚本可以安全地重新运行,因为那些已经拥有.config文件的开发者不会覆盖它们。 因此,可以想象将这个batch file作为预生成事件运行。 .default文件中的值对于新安装可能不完全正确,但是它们是一个合理的起点。
最终,每个开发人员最终都会看到如下所示的configuration文件文件夹:
这似乎有些复杂,但是开发人员彼此踩脚趾的麻烦绝对是可取的。
这里是web.config文件和Visual Studio 2010的解决scheme:
1)手动编辑你的Web应用程序.csproj文件来添加一个AfterBuild
目标像这样:
<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>
这个目标将转换对应于当前开发者login的Web.config文件 – 因此$(USERNAME)
variables – 与1)中创build的相应文件。 只有当每次构build时内容已经改变(以避免重新启动),即使本地Web.config是源代码控制的,它也会replace本地的Web.config,这就是为什么OverwriteReadOnlyFiles
被设置为True。 这一点实际上是有争议的。
2)为项目中的每个开发人员创build一个名为Web.[developer windows login].config
的文件Web.[developer windows login].config
。 (例如在以下屏幕截图中,我有两个名为smo和smo2的开发人员):
这些文件(每个开发者1个)可以/应该是源代码控制的。 他们不应该被标记为依赖主Web.config,因为我们希望能够单独检查出它们。
每个这个文件都代表一个应用于主Web.Config文件的转换。 这里描述了转换语法: Web应用程序项目部署的Web.config转换语法 。 我们重复使用Visual Studio提供的这个很酷的Xml文件转换任务。 这个任务的目的是合并 Xml元素和属性,而不是覆盖整个文件。
例如,下面是一个示例web.[dev login].config
,不pipeWeb.config文件的其余部分如何,都会更改名为“MyDB”的连接string:
<?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>
现在,这个解决scheme并不完美,因为:
- 在构build之后,开发者可能在本地具有不同的Web.Config而不是源控制系统
- 当从源代码pipe理系统获得新的Web.Config时,他们可能不得不强制本地写入
- 开发人员不应该检查/在主web.config。 它应该保留给less数人。
但至less,你只需要维护一个独特的主web.config加上每个开发人员一个转换文件。
App.config(不是networking)文件可以采取类似的方法,但我没有进一步详细说明。
在你的Web.config中使用其他文件的源代码
<configuration> <connectionStrings configSource="ConnectionStrings.config" /> ... </configuration>
保持web.config版本控制,而不要为ConnectionStrings.config。 现在所有的开发人员都有一个连接string的文件。
您可以对本地依赖的所有设置执行此操作。
我们使用machine.config来避免环境之间的web.config有差异。
忽略这些文件,并有一个Commom_Web.Config和Common_App.Config。 使用持续集成构build服务器和构build任务,将这两个任务重命名为正常名称,以便构build服务器可以完成其任务。
如何忽略文件,所以它永远不会被检入? 我遇到了类似的问题,并添加了web.config Subversion中的忽略列表。
但是在TFS中,这有点难,看到这篇文章如何做到这一点。
你可以应付的一种方法是有一个标记系统,并使用rake脚本来更改值。
一个更基本的方法可能是链接到你的web.config中的所有AppSettings的AppSettings.config文件(类似于连接)
<appSettings configSource="_configs/AppSettings.config" />
然后有一个文件夹与您的每个开发人员有一个版本在一个子文件夹(即/ _configs / dave /)。 然后,当开发人员正在处理他们自己的代码时,他们从子文件夹复制到链接文件夹的根目录。
您需要确保您将更改传达给这些文件(除非您使用标记)。 如果您将AppSettings.config文件放在源代码pipe理之外,并且只检查开发者个人文件夹(所有这些文件夹),那么他们将被迫复制正确的文件夹。
我更喜欢标记,但如果这只是一个快速修复,可能会更难以启动和运行。
我们有同样的问题,我们正在做的是
- 用testserver / production值检查web.config
- 开发人员去Windows资源pipe理器,并更改该文件的只读模式
- 编辑configuration以适应他们的环境。
- 只有在部署值发生更改或添加或删除任何configuration条目时,才会检入web.config。
- 这需要每个configuration条目的大量注释,因为它需要由每个dev改变
假设您正在使用Visual Studio,为什么不使用不同的解决schemeconfiguration? 例如:你可以有一个使用Web.config.debug的Debugconfiguration和一个使用Web.config.release的Releaseconfiguration。 Web.config.debug应该有类似的东西
<appSettings file="C:/Standard_Path_To_Configs/Standard_Name_For_Config.config">
使用文件Standard_Name_For_Config.config来显示所有的个人开发者设置,而Web.config.release总是具有生产设置。 您可以将默认configuration存储在某个源代码pipe理的文件夹中,并让新用户从那里进行访问。