在部署环境之间管理复杂的 Web.Config 文件
Posted
技术标签:
【中文标题】在部署环境之间管理复杂的 Web.Config 文件【英文标题】:Managing complex Web.Config files between deployment environments 【发布时间】:2010-09-30 12:35:30 【问题描述】:有谁知道在不同的构建/部署环境之间管理Web.Config
文件的任何好的工具/实用程序?
例如,我有一个 WCF 项目,在开发中我不想启用 SSL,但我确实希望在生产中启用它。我想要不同的日志记录设置、不同的数据库连接字符串、不同的错误处理、不同的文件路径……甚至是一些不同的 Unity 框架绑定(连接模拟用于单元测试,而不是用于部署的真实对象)。
维护Web.Config
的单个副本很痛苦,因为添加新的网络服务意味着编辑多个文件并保持它们同步。
我还注意到,如果您过多地手动使用 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>
connectionStrings_Debug
<configuration>
<connectionStrings>
<add name="connstr" connectionString="...dev..." />
</connectionStrings>
</configuration>
connectionStrings_Release
<configuration>
<connectionStrings>
<add name="connstr" connectionString="...prod..." />
</connectionStrings>
</configuration>
然后运行我的命令行工具,并传入配置(调试、发布、自定义...)
它会合并所有以_All" or
_
所以现在我将 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
当然,在典型的 Microsoft 方式中,任何功能只实现了 50%,它只适用于使用 web 部署的 web 项目。有一个插件可以在其他项目中启用转换,位于此处:http://www.hanselman.com/blog/SlowCheetahWebconfigTransformationSyntaxNowGeneralizedForAnyXMLConfigurationFile.aspx
您还可以使用BuildMaster 之类的工具来管理配置文件(以及构建、测试、数据库脚本等)
【问题讨论】:
【参考方案1】:我们将所有区域特定设置拆分为他们自己的配置文件。在 Web 应用程序的根目录下,我们创建一个配置文件夹并将区域特定设置放在那里。因此,任何位于 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 根目录中的文件替换为相应区域文件夹中的文件。文件结构类似于:
添加:这是源代码控制结构的外观,部署的应用程序只有配置目录,没有子文件夹或课程
\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 属性。也许我可以以某种方式融入它。如果visualstudio可以在构建时自动翻译它们并使用运行工具中的marcos,那就太好了......所以你可以指定“configSource=Config\$(ConfigurationName)\My.Config” 这是一个很棒的解决方案!在我所在的位置,开发人员使用 Visual Studio 进行开发工作,然后我们有一台使用 CruiseControl 和 NAnt 的构建机器来创建不同的版本(测试、阶段、生产……)。这对我们来说是完美的,因为我们可以创建一个 NAnt 任务来根据正在构建的版本复制适当的配置文件(或者如果它更适合您的环境,您可以使用 MSBuild 或 Visual Studio 来做同样的事情)。跨度> 【参考方案2】:您希望在 MSBuildCommunityTasks 中执行 XmlMassUpdate 任务(执行您尝试使用 xml 控制台应用程序执行的操作)
http://msbuildtasks.tigris.org/
这样使用
<XmlMassUpdate Condition=" '@(ConfigTemplateFile)'!='' And '@(ConfigSubstitutionsFile)'!=''"
ContentFile="@(ConfigTemplateFile)"
SubstitutionsFile="@(ConfigSubstitutionsFile)"
MergedFile="@(ConfigFile)"
ContentRoot="/configuration"
SubstitutionsRoot="/configuration/substitutions/$(Configuration)"/>
【讨论】:
【参考方案3】:您可以使用构建事件来管理您的网络配置。 Hanselman 有一篇关于它的好文章。
基本上,您在解决方案中拥有所有不同的 web.config,然后创建(一些)新的构建类型。根据您运行的构建类型,web.config 将复制到引用的一个!
【讨论】:
我也喜欢这种设置,它使用 Visual Studio 中的预构建事件来使用正确的 web.config 配置(.debug、.release、.deploy)覆盖 web.config。尽管它需要您维护多个配置文件,但它是一个干净且简单的设置。顺便说一句,它是“Hanselman”而不是“Hanselmen”。 正是我在同一时间写的:)【参考方案4】:我使用method explained by Scott Hanselman(他解释得比我能复制的要好得多,所以请点击链接:)) 对我来说效果很好......
【讨论】:
【参考方案5】:我用这个工具:xmlpreprocess
我们为部署脚本合并的每个环境维护单独的“属性”文件。
【讨论】:
【参考方案6】:我喜欢使用构建任务来automate 更改所需环境的配置文件。
【讨论】:
【参考方案7】:我们在配置文件中使用标签,这些标签在构建时被替换以反映预期的部署环境。我受到Lavablast blog的启发
很高兴只管理一个模板配置文件。
缺点是您不能轻易拥有自定义“部分”。
【讨论】:
【参考方案8】:老问题,但由于它在 Google 搜索中的排名很高,我认为添加 web.config transformation syntax 即 has been available since VS2010 是个好主意。使用此工具,您可以为不同的构建(调试/发布)拥有不同的 web.config 文件
以下是关于如何拥有两个连接字符串的简短摘要 - 一个用于开发(调试模式),一个用于生产(发布模式):
1- 在 web.config 文件中设置您的开发连接字符串。应该看起来像这样:
<connectionStrings>
<add name="myConnectionString" connectionString="Data Source=TestDBServer; (etc...)" />
</connectionStrings>
2- 展开您的 web.config 文件并打开 web.release.config
3- 使用Replace
function 将连接字符串替换为您想要用于生产的连接字符串。在本例中,您可以使用xdt:Locator="Match(name)"
属性将其与连接字符串的名称(myConnectionString)匹配:
<connectionStrings>
<add name="myConnectionString" xdt:Transform="Replace" xdt:Locator="Match(name)"
connectionString="Data Source=ProdDBServer; (etc...)" />
</connectionStrings>
4- 预览将在发布构建期间使用的 web.config 文件的转换,方法是右键单击 web.release.config 文件并选择Preview Transform。
【讨论】:
【参考方案9】:我传统上使用了您提到的多个 web.config。这可能会很痛苦,但可以通过 BeyoneComapare2 或 KDIff 等文件比较工具缓解...
【讨论】:
我爱Beyond Compare!我最喜欢的 5 个工具之一。【参考方案10】:烦恼:
我在第一次更新中提到了用于合并 XML 文档的我的小 cmd 行应用程序...好吧,我只使用 XmlDocument,并最终将其 .Save() 保存到 FileStream。
不幸的是,节点实际上并没有任何特定的顺序,显然,.NET 要求
我认为所有这些花哨的工具都应该让编程生活更轻松?
【讨论】:
【参考方案11】:我最喜欢的两种处理方式是:
A.保留目标机器上的设置* - 例如,在 Azure 中,您可以设置将覆盖 web.config 中的值的应用程序设置和连接字符串。 (* - 如果您的基础架构配置是动态的,则为目标机器定义)。
B.使构建/部署工具(TeamCity、Octopus Deploy 等、VS Team Services)注入环境特定值作为构建和/或部署的一部分。现代工具支持对敏感设置进行加密。
【讨论】:
以上是关于在部署环境之间管理复杂的 Web.Config 文件的主要内容,如果未能解决你的问题,请参考以下文章
将自定义 Web 部件部署到 SharePoint 2013
在 .net 核心中,它具有用于 Web 应用程序项目部署的 Web.config 转换语法?