如何在 Visual Studio 中为自定义配置文件添加配置转换?

Posted

技术标签:

【中文标题】如何在 Visual Studio 中为自定义配置文件添加配置转换?【英文标题】:How to add config transformations for a custom config file in Visual Studio? 【发布时间】:2016-04-16 13:33:01 【问题描述】:

我正在进行的项目涉及从配置文件中读取大量服务端点 (url)。由于列表非常大,我决定将它们保存在自定义配置文件中,以保持我的 web.config 干净且小巧。我将自定义部分包含在我的网站中,如下所示:

<mySection configSource="myConfig.config" />

我工作得很好。

但是在项目部署到不同环境的过程中出现了转换的问题。我有三个 web.config 文件:

Web.config

Web.Uat.config

Web.Release.config

虽然转换 web.config 有效,但自定义配置文件的转换在部署时失败。

有没有办法在部署期间转换自定义配置文件?

【问题讨论】:

对此进行了一些挖掘。明白啦;异地是的。是您正在寻找的东西吗? diaryofaninja.com/blog/2011/09/14/… 【参考方案1】:

默认情况下,Visual Studio 仅转换 web.config 文件。

如果您需要为 DEV、UAT、PROD 等环境进行转换的自定义配置文件,请尝试

    使用 Visual Studio 的自定义扩展,例如 SlowCheetah - XML Transforms,以实现配置转换预览功能。 为来自 Nuget 的项目添加 SlowCheetah 以提供内置转换。

一点细节:

从扩展和更新中添加 VS 扩展 SlowCheetah

右键单击您的 myconfig.config 并选择添加 transorm:

在每个定义的配置中插入您自己的转换规则,如下所示:

<services xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <service name="WebApplication1.Services.Service2" xdt:Transform="Replace" xdt:Locator="Match(name)" >
    <endpoint address="http://localhost:57939/Services/DebugService" behaviorConfiguration="WebApplication1.Services.Service2AspNetAjaxBehavior"
      binding="webHttpBinding" contract="WebApplication1.Services.Service2" />
  </service>
</services>

希望对你有帮助

【讨论】:

这并没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方留下评论。 - From Review 我认为这是对“...转换自定义配置文件...?”问题的答案。好的,将详细说明它是如何工作的。 当我重新安装 Visual Studio 时,答案被否决了。希望现在没事 它解决了这个问题,但我不得不将它添加为一个 nuget 包。 VS 扩展能够显示“预览转换”,但在发布时并未进行转换。 Visual Studio Gallery 上还有一个名为 Fast Koala 的扩展,虽然有一些细微的差别,但最终实现了相同的效果——另外还有构建时间(而不是发布时间)的可能性转换:visualstudiogallery.msdn.microsoft.com/…【参考方案2】:

我将稍微扩展一下 Andoni Ripoll Jarauta 的回答。

我们也遇到了类似的问题。我想从 web.config 文件中提取连接字符串以限制合并冲突。我还想在发布时创建一个包含静态信息的“发布”配置。

...很简单。创建自定义配置文件 webdb.config,并更新 web.config 文件。

例如。 web.config

<connectionStrings configSource="WebDB.config"/>

wedbdb.config(转换需要xml version="1.0")

<?xml version="1.0" encoding="utf-8"?>
<connectionStrings>
</connectionStrings>

接下来为 webdb.config 添加转换文件

WebDB.Debug.config 示例:

<?xml version="1.0" encoding="utf-8"?>

<connectionStrings xdt:Transform="Replace" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
    <add name="PRRADDataContainer" connectionString="metadata=~/PRRADData.csdl|~/PRRADData.ssdl|~/PRRADData.msl;provider=System.Data.SqlClient;provider connection string=';Data Source=localhost;Initial Catalog=;User ID=;Password=;multipleactiveresultsets=True;App=EntityFramework';" providerName="System.Data.EntityClient" />
    <add name="MyConnectionString" connectionString="Data Source=localhost;Initial Catalog=;Persist Security Info=True;User ID=;Password=;" providerName="System.Data.SqlClient" />
</connectionStrings>

WebDB.Release.config 示例:

<?xml version="1.0" encoding="utf-8"?>

<connectionStrings xdt:Transform="Replace" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
    <add name="PRRADDataContainer" connectionString="metadata=~/PRRADData.csdl|~/PRRADData.ssdl|~/PRRADData.msl;provider=System.Data.SqlClient;provider connection string=';Data Source=prod_server;Initial Catalog=;User ID=;Password=;multipleactiveresultsets=True;App=EntityFramework';" providerName="System.Data.EntityClient" />
    <add name="MyConnectionString" connectionString="Data Source=prod_server;Initial Catalog=;Persist Security Info=True;User ID=;Password=;" providerName="System.Data.SqlClient" />
</connectionStrings>

接下来我们需要添加一个构建后事件。这是通过简单地编辑 CSPROJ 文件来创建的。

<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterBuild">
    <TransformXml Source="WebDB.config" Transform="WebDB.$(Configuration).config" Destination="WebDB.config" />
</Target>

现在,当我在本地运行时,我将获得 WebDB.Debug.config,当我发布我的代码时,我只需要确保选择“发布”作为配置源。在这两种情况下,WebDB.config 文件都会在您构建时使用相应的文件进行更新。

注意:确保将“复制到输出目录”选项的 webdb.config、webdb.debug.config 和 webdb.release.config 设置为“不复制”。

希望这会有所帮助!

【讨论】:

【参考方案3】:

还有另一种方法不需要安装扩展程序也不需要使用构建事件。

假设您有这样的自定义配置:

myConfig.config myConfig.Uat.config myConfig.Release.config

然后在你的主要Web.config 你有这个:

<mySection configSource="myConfig.config" />

最后,在 Web.Uat.config 中添加如下转换:

<mySection configSource="myConfig.Uat.config" xdt:Transform="SetAttributes" />

这不是转换myConfig.config 文件,而是覆盖应该使用的自定义配置文件的名称。您可以对 Release 和任何其他环境执行相同操作。

您的myConfig.Uat.config 不应包含转换,它应该是基本自定义配置文件的副本,具有自定义环境的适当值。

不利的一面是,每次向基本自定义配置文件添加内容时,您还需要向其他 env 的配置文件添加内容(即使值应该通过 env 相同)。因此,我会考虑仅将这些自定义配置文件用于应在 env 之间更改的设置。

【讨论】:

【参考方案4】:

我一直在使用 SlowCheetah,但我发现了一些我认为更优雅的东西。只是告诉构建根据构建配置生成 .config 。

在您的项目中有一个 app.Release.config(或更多,取决于您的部署需要),您只需要编辑项目文件(如果您使用 C# 编程,则为 .csproj 文件)。在最后一个 &lt;/ItemGroup&gt;&lt;/Project&gt; 之间找到它的结尾并添加:

  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
  <Target Name="AfterBuild">
    <PropertyGroup>
      <OutputTypeName>$(OutputType)</OutputTypeName>
      <OutputTypeName Condition="'$(OutputTypeName)'=='Library'">dll</OutputTypeName>
      <OutputTypeName Condition="'$(OutputTypeName)'=='Module'">dll</OutputTypeName>
      <OutputTypeName Condition="'$(OutputTypeName)'=='Winexe'">exe</OutputTypeName>
    </PropertyGroup>
    <TransformXml Source="Config\app.config" Transform="Config\app.$(Configuration).config" Destination="$(OutputPath)\$(AssemblyName).$(OutputTypeName).config" />
  </Target>
</Project>

从 VisualStudio 保存并重新加载。在 Release 模式下编译并检查 &lt;MyProject&gt;.config 文件中的 bin/Release 文件夹,转换完成。

此示例适用于 Exe 和 Dll 文件以及任何 VisualStudio 版本,因为包括 this post help

【讨论】:

解决方案也适用于web.(configration).config??我正在使用 Visual Studio 2015 Web 应用程序。【参考方案5】:

由于 OP 在部署期间询问了 Web.config 转换,因此假设 WPP 已经存在。所以我入侵了 WPP。

我使用以下 sn-p 来转换 Umbraco 自己的配置文件(但实际上任何配置都适合):

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <UmbracoConfigsToTransform Include="Config\umbracoSettings.config">
      <DestinationRelativePath>Config\umbracoSettings.config</DestinationRelativePath>
    </UmbracoConfigsToTransform>
  </ItemGroup>

  <PropertyGroup>
    <CollectWebConfigsToTransformDependsOn>
      $(CollectWebConfigsToTransformDependsOn);
      CollectUmbracoConfigsToTransform
    </CollectWebConfigsToTransformDependsOn>
  </PropertyGroup>

  <Target Name="CollectUmbracoConfigsToTransform">
    <!-- The logic comes from the 'CollectWebConfigsToTransform' task -->
    <ItemGroup>
      <WebConfigsToTransform Include="@(UmbracoConfigsToTransform)">
        <Exclude>false</Exclude>
        <TransformFile>$([System.String]::new($(WebPublishPipelineProjectDirectory)\$([System.IO.Path]::GetDirectoryName($([System.String]::new(%(DestinationRelativePath)))))).TrimEnd('\'))\%(Filename).$(Configuration)%(Extension)</TransformFile>
        <TransformOriginalFolder>$(TransformWebConfigIntermediateLocation)\original</TransformOriginalFolder>
        <TransformFileFolder>$(TransformWebConfigIntermediateLocation)\assist</TransformFileFolder>
        <TransformOutputFile>$(TransformWebConfigIntermediateLocation)\transformed\%(DestinationRelativePath)</TransformOutputFile>
        <TransformScope>$([System.IO.Path]::GetFullPath($(WPPAllFilesInSingleFolder)\%(DestinationRelativePath)))</TransformScope>
      </WebConfigsToTransform>
    </ItemGroup>
  </Target>
</Project>

我将它命名为 Umbraco.wpp.targets 并放入项目的根目录中。 WPP 会自动导入它。

您所要做的就是添加一个转换文件(Config\umbracoSettings.Release.config 就是此示例的情况)。

【讨论】:

【参考方案6】:

我也需要转换自定义配置文件,但在类库中。 Andoni Ripoll Jarauta 的解决方案在我直接构建项目时有效,但是当我构建另一个引用它的项目时,转换后的文件不会被复制。我发现另外我必须将转换后的文件添加到AssignTargetPathsDependsOn 才能发生这种情况。这成功了:

<PropertyGroup>
  <AssignTargetPathsDependsOn>
    $(AssignTargetPathsDependsOn);
    BuildCustomConfig;
  </AssignTargetPathsDependsOn>
</PropertyGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="BuildCustomConfig">
  <TransformXml Source="MyCustom.config" Transform="MyCustom.$(Configuration).config" Destination="$(OutputPath)\MyCustom.config" />
  <ItemGroup>
    <Content Include="$(OutputPath)\MyCustom.config" Condition="Exists('$(OutputPath)\MyCustom.config')">
      <Link>MyCustom.config</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>
</Target>

【讨论】:

以上是关于如何在 Visual Studio 中为自定义配置文件添加配置转换?的主要内容,如果未能解决你的问题,请参考以下文章

如何禁用 Visual Studio 的默认构建并将其替换为自定义构建工具?

如何在 Visual Studio 2013 中为 sqlite 配置实体框架 6

如何在 .NET 中为自定义配置部分启用 configSource 属性?

如何在 EF Core 5 中为自定义 SQL 配置导航属性

我可以在 Visual Studio 中为 UnitTest/LoadTest 创建自定义 TestContext 计时器吗?

在 makefile 中为 Visual Studio C++ 构建定义宏