繁体   English   中英

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

[英]Developer specific app.config/web.config files in Visual Studio

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

现在每个开发人员都会有自己的配置文件,这些文件略有不同(连接本地数据库的不同连接字符串、不同的WCF端点等)

目前我们倾向于检查 app/web.config 文件并修改它们以满足我们的需要。

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

你如何处理这样的情况? 或者你根本没有这个问题?

我们使用的系统结合了此页面上的几个现有答案,并借鉴了 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文件的 .config 文件版本。 因此,一个新的源代码树看起来像这样:

替代文字

尽管如此,对于开发人员来说并没有什么用处,因为对于 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 文件中的值对于新安装可能不完全正确,但它们是一个合理的起点。

最终,每个开发人员最终得到的是一个配置文件文件夹,如下所示:

替代文字

这可能看起来有点令人费解,但绝对比开发人员相互踩踏的麻烦要好。

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

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

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

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

这是 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 应用程序项目部署的 Web.config 转换语法 我们重用 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 和一个转换文件。

可以对 App.config(不是 web)文件采取类似的方法,但我没有进一步详细说明。

我们使用 machine.config 来避免环境之间的 web.config 存在差异。

忽略该文件如何,因此它永远不会被签入? 我遇到了类似的问题,并将 web.config 添加到 Subversion 的忽略列表中。

但是在 TFS 中,它有点困难,请参阅有关如何执行此操作的帖子

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

一种更基本的方法可能是为 web.config 中的所有 AppSettings 设置一个 AppSettings.config 文件的链接(类似于连接),即

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

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

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

我更喜欢标记化,但如果这只是一个快速解决方案,那么启动和运行可能会更加困难。

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

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

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

假设您使用的是 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 始终具有生产设置。 您可以将默认配置存储在某个源代码控制文件夹中,并让新用户从那里获取它们。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM