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

时间:2016-01-12 03:31:27

标签: c# asp.net visual-studio transformation webdeploy

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

<mySection configSource="myConfig.config" />

我的工作非常好。

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

的Web.config

Web.Uat.config

Web.Release.config

转换web.config工作时,自定义配置文件的转换在部署时失败。

我可以在部署期间转换自定义配置文件吗?

6 个答案:

答案 0 :(得分:18)

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

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

  1. 使用Visual Studio的自定义扩展名(如SlowCheetah - XML Transforms)进行配置转换预览功能。
  2. 从Nuget SlowCheetah添加项目以提供构建转换。
  3. 一点点细节:

    从扩展程序和更新中添加VS Extension SlowCheetah Screen of Extensions and Updates

    右键单击 myconfig.config ,然后选择添加transorm: Screen of Extensions and Updates

    在每个定义的配置中插入您自己的转换规则:

    <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>
    

    希望它有用

答案 1 :(得分:5)

我将稍微介绍一下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添加转换文件

enter image description here

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设置为“请勿复制”。

希望这会有所帮助!

答案 2 :(得分:2)

我一直在使用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

答案 3 :(得分:0)

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

让我们假设您具有如下自定义配置:

  • 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不应包含转换,它应该是基本自定义配置文件的副本,并具有自定义环境的适当值。

缺点是每次您向基本的自定义配置文件中添加内容时,还需要将其他环境添加到配置文件中(即使该值在环境中应该相同)。因此,我考虑只将这些自定义配置文件用于应该在环境之间更改的设置。

答案 4 :(得分:0)

由于OP在部署期间询问了structure(list(values = c("", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "P", "C", "C"), ind = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "Parent", "Child", "Child"), output = c("", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "Parent", "Child", "Child")), class = "data.frame", row.names = c(NA, -19L)) 转换的情况,因此假设WPP已经在其中。因此,我入侵了WPP。

我使用以下代码段转换Umbraco自己的配置文件(但实际上任何配置都非常适合):

structure(list(values = c("P", "C", "C", "", "", "", "", "", 
"", "", "", "", "", "", "", "", "", "", ""), ind = c("Parent", 
"Child", "Child", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA), output = c("Parent", "Child", "Child", "", 
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "")), row.names = c(NA, 
-19L), class = "data.frame")

我将其命名为Web.config,然后放入项目的根目录下。 WPP会自动将其导入。

您要做的就是添加一个转换文件(<?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> 是此示例的情况)。

答案 5 :(得分:0)

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