Visual Studio中开发人员特定的app.config / web.config文件


93

我们有几个.NET项目,其中将某些设置存储在配置文件中。

现在,每个开发人员都有各自不同的配置文件(用于连接到本地数据库的不同连接字符串,不同的WCF端点等)。

目前,我们倾向于检出app / web.config文件并对其进行修改以适合我们的需求。

这会导致很多问题,因为从TFS获取最新版本时,有时会有人检查自己的设置或松散的自定义配置。

您如何处理这种情况?还是根本没有这个问题?


10
我投票决定重新开放,因为这是Visual Studio开发人员的常见问题,并且直接涉及开发人员正在使用的工具。(因此投票)
Christian Gollhardt

同意,这是一个长期存在的问题,因为我们的团队规模不断扩大,解决问题的各种尝试均不令人满意。
DiskJunky

Answers:


66

我们使用的系统结合了此页面上的几个现有答案,并借鉴了Scott Hanselman的建议

简而言之,我们要做的是拥有一个通用的app.config / web.config,并在单个文件中拥有大多数特定设置,如此处其他答案所建议的。例如对于我们的SMTP设置,app.config包含

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

该文件在源代码控制。但是,单个文件不是这样的:

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

但这并不是故事的结局。新开发者或全新安装的源呢?大部分配置已不再位于源代码控制中,手动构建它们所需的所有.config文件是一件很痛苦的事情。我更喜欢至少可以直接编译的源代码。

因此,我们确实在源代码管理中保留了一个名为.config.default文件的版本。因此,新鲜的源树如下所示:

替代文字

尽管如此,对开发人员而言并没有任何用处,因为对于Visual Studio而言,它们只是无意义的文本文件。因此,批处理文件copy_default_config.bat负责根据.config.default文件创建一组初始的.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文件的开发人员不会覆盖它们。因此,可以想象的是,可以将此批处理文件作为预构建事件来运行。.default文件中的值对于全新安装而言可能并不完全正确,但它们是一个合理的起点。

最终,每个开发人员最终都会得到一个配置文件文件夹,看起来像这样:

替代文字

这似乎有些令人费解,但是绝对比开发人员踩到对方的麻烦更可取。


为什么不在存储库中直接拥有主.config而不在单个库中拥有?
2011年

6
多么痛苦,我们需要一个更好的解决方案。我设置了类似的方法,但对它如此脆弱并且仍然需要向新开发人员进行解释感到厌倦。
jpierson 2012年

@Gavin,如果我尝试运行您概述的bat文件,则会收到错误消息:'∩╗┐@ echo'无法识别为内部或外部命令,可操作程序或批处理文件。
奥斯丁

2
@Austin,您似乎在“ @echo”之前有一些不可打印的垃圾,其中一部分可能是Unicode字节顺序标记?可能是复制/粘贴出现问题,或者批处理文件以无法正确读取的编码保存。
加文2015年

21

在您的Web.config中,使用其他文件中的源

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

将web.config保留在版本控制中,不要对ConnectionStrings.config执行。现在,所有开发人员都有一个用于连接字符串的文件。

您可以对本地相关的所有设置执行此操作。


1
这对我来说很好。另请参阅:davidgiard.com/2012/05/25/…ConnectionStrings.config 文件必须与应用程序或Web配置位于同一文件夹中。另外,必须将其属性更改为“如果较新则复制”以输出。并且ConnectionStrings.config文件需要带有打开和关闭元素的完整部分。您还必须设置版本控制以忽略该文件,因此每个文件都是特定于用户的。
Jeffrey Roughgarden

1
我使用了<appSettings file =“ ..”>选项,因为我不得不合并设置
Spikolynn

1
@JeffreyRoughgarden如果在解决方案资源管理器中包含ConnectionStrings.config文件,该文件是否不必存在于filesysterm上?如果确实如此,则意味着您已将其检入源代码管理。这是我们试图摆脱的最初问题。
耶斯

20

这是针对web.config文件和Visual Studio 2010的解决方案:

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>

此目标将转换与登录的当前开发人员相对应的Web.config文件(因此为$(USERNAME)变量),以及在1)中创建的相应文件。仅在每次构建时更改了内容(以避免重新启动)时,它才会替换本地Web.config,即使本地Web.config是受源代码控制的,这就是将 OverwriteReadOnlyFiles设置为True的原因。这一点实际上是有争议的。

2)创建一个为Web.[developer windows login].config项目中的每个开发人员命名的文件。(例如,在以下屏幕截图中,我有两个名为smo和smo2的开发人员):

在此处输入图片说明

这些文件(每个开发人员1个文件)可以/应该由源代码控制。不应将它们标记为依赖于主Web.config,因为我们希望能够单独检出它们。

每个文件都代表一个转换,该转换将应用于主Web.Config文件。此处描述了转换语法:Web.config Web应用程序项目部署的转换语法。我们将重用Visual Studio附带的这个很酷的Xml文件转换任务。此任务的目的是合并 Xml元素和属性,而不是覆盖整个文件。

例如,以下示例web.[dev login].config更改了一个名为“ MyDB”的连接字符串,而与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>

现在,此解决方案并不完美,因为:

  • 构建后,开发人员本地的Web.Config可能与源代码控制系统中的Web.Config不同
  • 从源代码控制系统获取新的Web.Config时,他们可能必须强制进行本地写入
  • 开发人员不应在主要web.config中签出/签入。它应该保留给很少的人。

但是至少,您只需要维护一个唯一的主web.config以及每个开发人员一个转换文件。

对于App.config(不是Web)文件,可以采用类似的方法,但是我没有进一步阐述。


我将Web.config重命名为Web.base.config,创建了一个新的Web.config文件,然后在步骤1中从<Copy SourceFiles =“ web.config”>更改为<Copy SourceFiles =“ web.base.config”。这样做,我可以拥有一个本地web.config,在源代码管理中可以忽略它。
S. Baggy 2014年

这仍然不是理想的选择,但我比其他解决方案更喜欢
JMK

您认为可以使用不存在的web.default.configwhen web.$(USERNAME).config吗?顺便谢谢您的回答。
Christian Gollhardt


0

如何忽略文件,使其永远不会被检入?我遇到了类似的问题,并已将web.config添加到Subversion中的忽略列表。

但是在TFS中,它要困难一些,请参阅这篇文章中的操作方法。


0

您可以解决的一种方法是拥有标记化的系统并使用rake脚本更改值。

一种更基本的方法是为您的web.config中的所有AppSettings提供一个指向AppSettings.config文件的链接(类似于连接),即

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

然后有一个文件夹,每个开发人员的子文件夹中都有一个版本(即/ _configs / dave /)。然后,当开发人员处理自己的代码时,他们将从子文件夹复制到链接文件夹的根目录。

您将需要确保传达对这些文件的更改(除非您标记化)。如果您将AppSettings.config文件置于源代码管理之外,并且仅检入devs的单个文件夹(所有文件夹),那么它们将被迫复制正确的文件夹。

我更喜欢令牌化,但是如果这只是为了快速解决,可能会更难启动和运行。


0

忽略文件,并拥有Commom_Web.Config和Common_App.Config。使用具有构建任务的连续集成构建服务器,该任务将这两个重命名为常规名称,以便构建服务器可以完成其工作。


这需要在开发机器上完成,然后再构建服务器
twarz01

不能在构建服务器上进行这种重命名。公用配置文件存储在Subversion中,它们独立于特定的开发人员。每个开发人员都运行其个人配置文件以在其计算机上进行开发,并且不关心提交该配置文件,因为它不是Subversion的一部分。
Arthis

这不支持的事情是开发人员调试应用程序。web.config在调试过程中使用源文件夹中的根目录。如果,例如,添加web.config.gitignore,要么需要用户复制Commom_Web.Configweb.config和编辑它自己的幻想,你的存在方式的一部分。但是,当您需要在所有开发人员的机器上编辑相同的内容(例如在任何地方都应该相同的system.web/compilation部分或特定appSettings内容)时,此方案就会瓦解。
宾基

0

我们有同样的问题,我们正在做的是

  • 使用testserver /生产值检入web.config
  • 开发人员转到Windows资源管理器并更改文件的只读模式
  • 编辑配置以适合其环境。
  • 仅当更改部署值或添加或删除任何配置条目时,才签入web.config。
  • 每个配置条目都需要大量注释,因为每个开发人员都需要对其进行更改

1
这在商店中可能会更好,在这些商店中,您使用的源代码控制默认将字段设置为只读,但对于其他使用Subversion的字段,它可能无法正常工作。我们可以在存储库中设置只读权限以防止其提交,但是需要在每个分支的每个配置文件上设置该权限。
jpierson 2012年

对于我们中那些不使用TFS之类的人来说,这种解决方案如何工作尚不清楚。您能再给些背景吗?另外,这是否要求开发人员要小心并且不要意外检出文件?
宾基

-1

假设您使用的是Visual Studio,为什么不使用其他解决方案配置?例如:您可以拥有一个使用Web.config.debug的调试配置和一个使用Web.config.release的发布配置。Web.config.debug应该有类似的东西

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

文件Standard_Name_For_Config.config具有所有个人开发人员设置,而Web.config.release始终具有生产设置。您可以将默认配置存储在某个源代码控制的文件夹中,并让新用户从那里获取它们。


然后,每个将为项目做出贡献的用户都将需要拥有自己的构建配置。这似乎没有规模,也不支持接受捐款的项目。
宾基
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.