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

有谁知道在不同的构build/部署环境之间pipe理Web.Config文件的好工具/实用程序吗?

例如,我有一个开发中的WCF项目,我不想启用SSL,但是我希望在生产中启用它。 我想要不同的日志logging设置,不同的数据库连接string,不同的error handling,不同的文件path…甚至一些不同的统一框架绑定(unit testing,而不是真正的对象部署)。

保持Web.Config单独副本是一个痛苦,因为添加新的Web服务意味着编辑多个文件并保持同步。

我也注意到,如果你手工过多地使用Web.Config ,如果你尝试使用“add item”向导来为WCF添加一个新的Web服务,Visual Studio将会窒息,因为它必须修改Web.Config来添加端点,并且不能再parsing它。 所以我必须小心不要使现有的Web.Config无效。

我也想过使用一些正则expression式来replace,只是在预编译命令中build立一个新的Web.Config 。 这似乎是迄今为止最好的select…

任何其他的想法? 看起来这应该是一个非常普遍的问题,因为Web.Config在开发和生产部署之间可能永远不会相同。


更新:

我决定编写一个快速的控制台应用程序,将所有的XML文件在一个给定的目录,并合并成一个,只包括基于名称的某些文件。

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

WebConfig_All

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

connectionStrings_Debug

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

connectionStrings_Release

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

然后运行我的命令行工具,并传入configuration(debugging,释放,自定义…),它将合并所有以_All" or _ <configuration>`结尾的文件。

所以现在我在单个WebConfig_All文件中有80%的Web.Config,而每个构buildconfiguration中有20%的自定义内容在不同的文件中。 我可以运行我的命令行工具作为预生成任务在VisualStudio中,或从NAnt,或任何我想要的…

我也使我的XML合并逻辑足够好处理像这样的东西:

 <x> <ya="1"> <za="1"/> </y> </x> 

合并

 <x> <ya="1"> <za="2"/> </y> <ya="2"/> </x> 

结果是:

 <x> <ya="1"> <za="1"/> <za="2"/> </y> <ya="2"/> </x> 

目前看起来不错… 🙂


跟进:

这个话题现在有点老了,所以我想指出,VisualStudio 2010有一个function可以完成web.config内置的转换: http : //msdn.microsoft.com/en-us/vstudio/Video/ff801895

当然,在典型的微软方式中,只有50%的方式实现任何function,它只适用于使用Web部署的Web项目。 有一个插件来启用其他项目的转换,位于这里: http : //www.hanselman.com/blog/SlowCheetahWebconfigTransformationSyntaxNowGeneralizedForAnyXMLConfigurationFile.aspx

你也可以使用像BuildMaster这样的工具来pipe理configuration文件(以及构build,testing,数据库脚本等)

我们将所有区域特定的设置分解成它们自己的configuration文件。 在Web应用程序的根目录下,我们创build一个configuration文件夹,并在其中放置特定于区域的设置。 因此,无论configuration文件的根目录下的任何文件都会被拾取。

我们的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> . . . 

因此,如果我们正在部署到发布区域,构build工具将只需要执行一个操作,将config的根目录中的文件replace为相应区域文件夹中的文件。 文件结构如下所示:

ADDED:这是源代码pipe理结构的外观,已部署的应用程序只具有没有子文件夹或课程的configuration目录

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

这是相当干净的,并支持任何自动化的构build工具(复制/replace文件)。 好的一面是,开发人员可以创build不同的风格,并保持在源代码控制下,而不会影响“真实”的configuration。

你想在MSBuildCommunityTasks中的XmlMassUpdate任务(做你正在尝试用你的XML控制台应用程序)

http://msbuildtasks.tigris.org/

像这样使用它

  <XmlMassUpdate Condition=" '@(ConfigTemplateFile)'!='' And '@(ConfigSubstitutionsFile)'!=''" ContentFile="@(ConfigTemplateFile)" SubstitutionsFile="@(ConfigSubstitutionsFile)" MergedFile="@(ConfigFile)" ContentRoot="/configuration" SubstitutionsRoot="/configuration/substitutions/$(Configuration)"/> 

你可以使用Build Events来pipe理你的网页configuration。 Hanselman有一个很好的文章。

基本上,你在解决scheme中拥有所有不同的web.configs,然后创build(一些)新的构buildtypes。 根据你build立的types你运行一个web.config被复制到引用的一个!

我使用的是由Scott Hanselman解释的方法 (他解释得好得多,我可以重现这个,所以请点击链接:))它对我来说工作得很好…

我使用这个工具: xmlpreprocess

我们为由部署脚本合并的每个环境维护单独的“属性”文件。

我喜欢使用构build任务来自动更改所需环境的configuration文件。

我们在configuration文件中使用了标签,这些标签在构build时被replace,以反映预期的部署环境。 我受到了Lavablast博客的启发

只有一个模板configuration文件可以pipe理是很好的。

缺点是你不容易有自定义的“部分”。

老问题,但由于它在Googlesearch中的排名很高,我认为添加自VS2010以来已经可用的web.config转换语法是一个好主意。 有了这个工具,你可以为不同的版本(debugging/发布)提供不同的web.config文件

下面是关于如何有两个连接string的简短摘要 – 一个用于开发(debugging模式)和一个用于生产(发布模式):

1-在web.config文件中设置您的开发连接string。 应该看起来像这样:

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

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

web.config中

3-使用“ Replacefunction将连接stringreplace为您要生产的连接string。 在本例中,您可以使用xdt:Locator="Match(name)"属性将其与连接string(myConnectionString)的名称进行匹配:

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

4-通过右键单击web.release.config文件并select“ 预览变换”预览将在发布版本中使用的web.config文件的变换

在这里输入图像说明

正如你所提到的,我一直使用多个web.configs。 这可能是一个痛苦,但它可以通过文件比较工具(如BeyoneComapare2或KDIff)来缓解…

烦恼:

我提到了我的小命令行应用程序合并XML文档在我的第一次更新…嗯,我只是使用XmlDocument,并最终只是.Save()它到一个FileStream。

不幸的是,这些节点实际上并没有特定的顺序,显然,.NET 要求 <configSections>元素是文档的第一个子元素。

我认为所有这些奇特的工具都应该让编程生活变得更简单

我最喜欢的两种处理方式是:

答:保持目标机器上的设置* – 在Azure中,例如,您可以设置将覆盖web.config中的值的应用程序设置和连接string。 (* – 如果您的基础架构configuration是dynamic的,则为目标机器定义)。

B.使构build/部署工具(TeamCity,Octopus Deploy等VS Team Services)在构build和/或部署中注入特定于环境的值。 现代工具支持敏感设置的encryption。