在部署环境之间管理复杂的Web.Config文件

53

有没有好的工具/实用程序,可以在不同的构建/部署环境之间管理Web.Config文件?

例如,在开发中我不希望启用SSL,但在生产中我要启用它。 我想要不同的日志记录设置、不同的数据库连接字符串、不同的错误处理、不同的文件路径......甚至一些不同的Unity框架绑定(为单元测试划分模拟对象,而不是为部署划分真正的对象)。

维护Web.Config的各个副本很麻烦,因为添加新的web服务意味着编辑多个文件并保持它们同步。

我还注意到,如果你通过手动修改 Web.Config 来改得太复杂,当您尝试使用“添加项”向导添加WCF的新Web服务时,Visual Studio会崩溃,因为它必须修改 Web.Config 来添加端点,无法再解析它。所以我必须小心不要使现有的 Web.Config 无效。

我也考虑过只使用一些正则表达式进行替换,并在预建命令中构建一个新的 Web.Config 。这似乎是迄今为止最好的选择...

还有其他想法吗?这似乎应该是一个非常常见的问题,因为在开发和生产部署之间 Web.Config 应该永远不会相同。

更新:

我决定编写一个快速控制台应用程序,将给定目录中的所有xml文件合并成一个文件,并仅根据名称包括某些文件。

所以我可以在一个目录中:

WebConfig_All

<configuration>
  <configSections>
    ...
  </configSections>
  <system.web>
    ...
  </system.web>
</configuration>

连接字符串_Debug

<configuration>
  <connectionStrings>
    <add name="connstr" connectionString="...dev..." />
  </connectionStrings>
</configuration>

连接字符串_Release

<configuration>
  <connectionStrings>
    <add name="connstr" connectionString="...prod..." />
  </connectionStrings>
</configuration>
然后运行我的命令行工具,并传入配置(Debug、Release、自定义...),它将合并所有以"_All"或"_<configuration>"结尾的文件。
现在我将80%的Web.Config放在一个名为WebConfig_All的文件中,而将20%的自定义内容放在每个构建配置的单独文件中。然后我可以将我的命令行工具作为预构建任务在VisualStudio中运行,也可以在NAnt或其他任何地方运行...
我还改进了XML合并逻辑,使其能够处理诸如:
<x>
  <y a="1">
    <z a="1"/>
  </y>
</x>
合并
<x>
  <y a="1">
    <z a="2"/>
  </y>
  <y a="2"/>
</x>

导致结果:

<x>
  <y a="1">
    <z a="1"/>
    <z a="2"/>
  </y>
  <y a="2"/>
</x>

看起来目前还不错... :)


跟进:

这个主题现在有点老了,所以我想指出VisualStudio 2010具有内置的执行web.config转换的功能: http://msdn.microsoft.com/en-us/vstudio/Video/ff801895

当然,按照微软一贯的方式,这个功能只对使用Web Deploy的 Web 项目有效。这里有一个插件可以启用其他项目中的转换:http://www.hanselman.com/blog/SlowCheetahWebconfigTransformationSyntaxNowGeneralizedForAnyXMLConfigurationFile.aspx

你也可以使用诸如BuildMaster之类的工具来管理配置文件(以及构建、测试、数据库脚本等)。

11个回答

21

我们将所有区域特定的设置分离到它们自己的配置文件中。 在 Web 应用程序的根路径下,我们创建一个 config 文件夹,并放置区域特定的设置文件。 因此,无论哪个文件存储在 config 根目录下,都会被选中。

我们的 web.config 大致如下:

.
.
.
<appSettings configSource="config\appSettings.config"/>
<nlog configSource="config\nlog.config"/>
<applicationSettings>
    <MyApp.UI.Properties.Settings configSource="config\Settings.APGUI.config"/>
    <MyApp.BusinessServices.Properties.Settings configSource="config\Settings.Business.config"/>
    <MyApp.Auditing.Properties.Settings configSource="config\Settings.Auditing.config"/>
</applicationSettings>
.
.
.

如果我们正在部署到发布区域,构建工具将只需执行一个操作,即将config根目录中的文件替换为相应区域文件夹中的文件。文件结构大致如下:

添加说明:这是源代码控制结构的样子,部署的应用程序只会有config目录,没有子文件夹或子目录。

\Root
   web.config    
   \Config    
       appsettings.config    
       services.config    
       logging.config    
       \release    
          appsettings.config    
          services.config    
          logging.config    
       \debug
          appsettings.config    
          services.config    
          logging.config

这是一个相当干净的方法,并且受到任何自动化构建工具(复制/替换文件)的支持。好处在于开发人员可以创建不同的版本并将它们保存在源代码控制下,而不会影响“真实”的配置。


我喜欢使用configSource属性。也许我可以以某种方式将其合并。如果Visual Studio可以在构建时自动翻译它们并使用运行工具中的宏,那就太好了...这样你就可以指定“configSource = Config \ $(ConfigurationName)\ My.Config”。 - CodingWithSpike
这是一个非常好的解决方案!在我的工作环境中,开发人员使用Visual Studio进行开发工作,然后我们有一个使用CruiseControl和NAnt的构建机器来创建不同的发布版本(测试、阶段、生产等)。这对我们来说非常完美,因为我们可以只需创建一个NAnt任务来根据正在构建的发布版本复制适当的配置文件(或者如果适合您的环境,您也可以使用MSBuild或Visual Studio执行相同的操作)。 - Ogre Psalm33

7
你可以使用构建事件来管理你的Web配置文件。Hanselman有一篇很好的文章介绍了这个功能。
基本上,你在解决方案中拥有不同的Web.config文件,然后创建(某些)新的构建类型。根据构建类型运行时,会复制一个Web.config文件到引用的文件夹中!

我也喜欢使用Visual Studio中的预构建事件来覆盖web.config,以便使用正确的web.config配置(.debug、.release、.deploy)。虽然这需要你维护多个配置文件,但它是一个干净而简单的设置。顺便说一下,应该是"Hanselman"而不是"Hanselmen"。 - PropellerHead
把以下與程式設計相關的內容從英文翻譯成中文。僅返回已翻譯的文字,不要進行解釋。 - Cohen

7
你想要使用MSBuildCommunityTasks中的XmlMassUpdate任务(可以完成你在xml控制台应用程序中尝试做的事情)。 http://msbuildtasks.tigris.org/ 像这样使用它:
  <XmlMassUpdate Condition=" '@(ConfigTemplateFile)'!='' And '@(ConfigSubstitutionsFile)'!=''"
    ContentFile="@(ConfigTemplateFile)"
    SubstitutionsFile="@(ConfigSubstitutionsFile)"
    MergedFile="@(ConfigFile)"
    ContentRoot="/configuration"
    SubstitutionsRoot="/configuration/substitutions/$(Configuration)"/>

4

4
我使用这个工具:xmlpreprocess 我们为每个环境维护单独的“属性”文件,并通过部署脚本进行合并。

2
我喜欢使用构建任务来自动化更改所需环境的配置文件。

2
我们在配置文件中使用标签,在构建时替换这些标签以反映预期的部署环境。我受到Lavablast博客的启发。
只需要管理一个模板配置文件是很不错的。
缺点是你不能轻松地拥有自定义的“部分”。

2
旧问题,但由于它在谷歌搜索中排名很高,我认为添加web.config转换语法是一个好主意,这个工具自VS2010以来就可用。使用此工具,您可以为不同的构建(Debug/Release)拥有不同的web.config文件。

以下是如何拥有两个连接字符串(开发模式和生产模式)的简短摘要:

1- 在web.config文件中设置您的开发连接字符串。应该类似于这样:

 <connectionStrings>
    <add name="myConnectionString"  connectionString="Data Source=TestDBServer; (etc...)" />
  </connectionStrings>

2- 扩展您的web.config文件并打开web.release.config文件。

web.config

3- 使用Replace函数替换连接字符串为生产环境所需的字符串。您可以使用xdt:Locator="Match(name)"属性将其与连接字符串名称(本示例中为myConnectionString)匹配:

<connectionStrings>
    <add name="myConnectionString"  xdt:Transform="Replace" xdt:Locator="Match(name)" 
         connectionString="Data Source=ProdDBServer; (etc...)" />
  </connectionStrings>

4- 右键单击 web.release.config 文件并选择 预览转换,以预览在发布构建期间将使用的 web.config 文件的转换。

enter image description here


1
我过去一直按照你提到的方式使用多个web.config文件。虽然可能有些麻烦,但可以通过文件比较工具(如Beyond Compare 2或KDiff)来缓解这个问题...

1
我喜欢Beyond Compare!它是我最喜欢的五个工具之一。 - CodingWithSpike

0

烦恼:

我在第一次更新中提到了我的小命令行应用程序,用于合并XML文档... 好吧,为了做到这一点,我只是使用XmlDocument,并最终将其保存到FileStream中。

不幸的是,节点没有任何特定的顺序,而且显然,.NET 要求 <configSections> 元素是文档的第一个子元素。

我以为所有这些花哨的工具都应该让编程生活变得更加容易


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接