如何在 Visual Studio 中为自定义配置文件添加配置转换?
How to add config transformations for a custom config file in Visual Studio?
我正在从事的项目涉及从配置文件中读取大量服务端点 (url)。由于列表会非常大,我决定将它们保存在一个自定义配置文件中,以保持我的 web.config 干净和小巧。我将自定义部分包含在我的网站中,如下所示:
<mySection configSource="myConfig.config" />
我工作得很好。
但是在项目部署到不同环境的过程中出现了转换的问题。我有三个 web.config 个文件:
Web.config
Web.Uat.config
Web.Release.config
虽然转换 web.config 有效,但自定义配置文件的转换在部署时失败。
有没有一种方法可以在部署期间转换自定义配置文件?
Visual Studio 默认只转换 web.config 个文件。
如果您需要为 DEV、UAT、PROD 等环境转换的自定义配置文件,请尝试
- 使用 Visual Studio 的自定义扩展,例如 SlowCheetah - XML Transforms 的配置转换预览功能。
- 从 Nuget SlowCheetah 为项目添加以提供内置转换。
一点细节:
从扩展和更新中添加 VS 扩展 SlowCheetah
右键单击您的 myconfig.config 并选择添加变形:
在每个定义的配置中插入您自己的转换规则,如下所示:
<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>
希望对您有所帮助
我一直在使用 SlowCheetah,但我发现了一些我认为更优雅的东西。只是告诉构建根据构建配置生成 .config。
在您的项目中有一个 app.Release.config(或更多,具体取决于您的部署需要),您只需编辑项目文件(如果您使用 C# 编程,则为 .csproj 文件)。找到它的结尾,在最后一个 </ItemGroup>
和 </Project>
之间并添加:
</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 重新加载。在发布模式下编译并检查 <MyProject>.config
文件上的 bin/Release 文件夹,转换已完成。
此示例适用于 Exe 和 Dll 文件以及任何 VisualStudio 版本,因为包括 this post help
我将稍微扩展一下 Andoni Ripoll Jarauta 的回答。
我们遇到了类似的问题。我想从 web.config 文件中提取连接字符串以限制合并冲突。我还想在发布时创建一个包含静态信息的 "release" 配置。
...很简单。创建自定义配置文件 webdb.config,并更新 web.config 文件。
例如。
web.config
<connectionStrings configSource="WebDB.config"/>
wedbdb.config(转换需要xmlversion="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,当我发布我的代码时,我只需要确保 select "Release" 作为配置源.在这两种情况下,WebDB.config 文件将在您构建时使用相应的文件进行更新。
注意:请确保将 webdb.config、webdb.debug.config 和 webdb.release.config 设置为 "Do not copy" 以获得 "Copy to Output Directory" 选项。
希望对您有所帮助!
还有另一种方法,不需要安装扩展,也不需要使用构建事件。
假设您有这样的自定义配置:
- 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
不应包含转换,它应该是基本自定义配置文件的副本,具有适合自定义环境的值。
缺点是每次向基本自定义配置文件添加内容时,您还需要向其他 envs 的配置文件添加内容(即使通过 envs 的值应该相同)。所以我会考虑只使用这些自定义配置文件来设置应该在 envs 之间更改。
由于 OP 在部署期间询问了 Web.config
转换,因此我们假设 WPP 已经存在。所以我黑了 WPP。
我使用以下代码片段来转换 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
是这个示例的例子)。
我有类似的需要来转换自定义配置文件,但在 class 库中。 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>
我正在从事的项目涉及从配置文件中读取大量服务端点 (url)。由于列表会非常大,我决定将它们保存在一个自定义配置文件中,以保持我的 web.config 干净和小巧。我将自定义部分包含在我的网站中,如下所示:
<mySection configSource="myConfig.config" />
我工作得很好。
但是在项目部署到不同环境的过程中出现了转换的问题。我有三个 web.config 个文件:
Web.config
Web.Uat.config
Web.Release.config
虽然转换 web.config 有效,但自定义配置文件的转换在部署时失败。
有没有一种方法可以在部署期间转换自定义配置文件?
Visual Studio 默认只转换 web.config 个文件。
如果您需要为 DEV、UAT、PROD 等环境转换的自定义配置文件,请尝试
- 使用 Visual Studio 的自定义扩展,例如 SlowCheetah - XML Transforms 的配置转换预览功能。
- 从 Nuget SlowCheetah 为项目添加以提供内置转换。
一点细节:
从扩展和更新中添加 VS 扩展 SlowCheetah
右键单击您的 myconfig.config 并选择添加变形:
在每个定义的配置中插入您自己的转换规则,如下所示:
<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>
希望对您有所帮助
我一直在使用 SlowCheetah,但我发现了一些我认为更优雅的东西。只是告诉构建根据构建配置生成 .config。
在您的项目中有一个 app.Release.config(或更多,具体取决于您的部署需要),您只需编辑项目文件(如果您使用 C# 编程,则为 .csproj 文件)。找到它的结尾,在最后一个 </ItemGroup>
和 </Project>
之间并添加:
</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 重新加载。在发布模式下编译并检查 <MyProject>.config
文件上的 bin/Release 文件夹,转换已完成。
此示例适用于 Exe 和 Dll 文件以及任何 VisualStudio 版本,因为包括 this post help
我将稍微扩展一下 Andoni Ripoll Jarauta 的回答。
我们遇到了类似的问题。我想从 web.config 文件中提取连接字符串以限制合并冲突。我还想在发布时创建一个包含静态信息的 "release" 配置。
...很简单。创建自定义配置文件 webdb.config,并更新 web.config 文件。
例如。 web.config
<connectionStrings configSource="WebDB.config"/>
wedbdb.config(转换需要xmlversion="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,当我发布我的代码时,我只需要确保 select "Release" 作为配置源.在这两种情况下,WebDB.config 文件将在您构建时使用相应的文件进行更新。
注意:请确保将 webdb.config、webdb.debug.config 和 webdb.release.config 设置为 "Do not copy" 以获得 "Copy to Output Directory" 选项。
希望对您有所帮助!
还有另一种方法,不需要安装扩展,也不需要使用构建事件。
假设您有这样的自定义配置:
- 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
不应包含转换,它应该是基本自定义配置文件的副本,具有适合自定义环境的值。
缺点是每次向基本自定义配置文件添加内容时,您还需要向其他 envs 的配置文件添加内容(即使通过 envs 的值应该相同)。所以我会考虑只使用这些自定义配置文件来设置应该在 envs 之间更改。
由于 OP 在部署期间询问了 Web.config
转换,因此我们假设 WPP 已经存在。所以我黑了 WPP。
我使用以下代码片段来转换 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
是这个示例的例子)。
我有类似的需要来转换自定义配置文件,但在 class 库中。 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>