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

3pvhb19x  于 2023-05-23  发布在  其他
关注(0)|答案(6)|浏览(213)

我正在做的项目涉及到从配置文件中阅读大量的服务端点(url)。由于列表会相当大,我决定将它们保存在一个自定义配置文件中,以保持我的web.config干净和小。我在我的网站上添加了自定义部分,如下所示:

<mySection configSource="myConfig.config" />

我工作得很好。
但是在将项目部署到不同环境的过程中,转换的问题出现了。我有三个web.config文件:
Web.config
Web.Uat.config
Web.Release.config
当转换web.config工作时,自定义配置文件的转换在部署时失败。
有没有一种方法可以在部署过程中转换自定义配置文件?

mlmc2os5

mlmc2os51#

默认情况下,VisualStudio仅转换web.config文件。
如果您需要为DEV、UAT、PROD等环境转换自定义配置文件,请尝试
1.使用Visual Studio的自定义扩展,如SlowCheetah - XML Transforms用于配置转换预览功能。
1.从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>
cs7cruho

cs7cruho2#

我将对Andoni Ripoll Jarauta的回答进行一点扩展。
我们面临着类似的问题。我想从web.config文件中提取连接字符串来限制合并冲突。我还想在发布时创建一个包含静态信息的“发布”配置。
很简单创建自定义配置文件webdb.config,并更新web.config文件。
ex.web.config

<connectionStrings configSource="WebDB.config"/>

config(转换需要xml版本=“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,当我发布我的代码时,我只需要确保选择“Release”作为配置源。在这两种情况下,WebDB.config文件都将在生成时使用相应的文件进行更新。
注意:请确保将webdb.config、webdb.debug.config和webdb.release.config设置为“复制到输出目录”选项的“不复制”。

bjp0bcyl

bjp0bcyl3#

我一直在使用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重新加载。在Release模式下编译并检查<MyProject>.config文件上的bin/Release文件夹,转换完成。
此示例适用于EXE和Dll文件以及任何VisualStudio版本,因为包含this post help

iugsix8n

iugsix8n4#

还有一种方法不需要安装扩展,也不需要使用构建事件。
让我们假设你有这样的自定义配置:

  • 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文件,而是覆盖应该使用的自定义配置文件的名称。您可以对版本和任何其他环境执行相同的操作。
您的myConfig.Uat.config不应该包含转换,它应该是基本自定义配置文件的副本,并具有自定义环境的适当值。
缺点是每次你在基础自定义配置文件中添加一些东西时,你也需要添加到其他env的配置文件中(即使通过env的值应该是相同的)。所以我会考虑只使用这些自定义配置文件来进行应该在env之间更改的设置。

b09cbbtk

b09cbbtk5#

我有一个类似的需要转换一个自定义配置文件,但在一个类库。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>
q3aa0525

q3aa05256#

由于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)。

相关问题