Web 配置转换不起作用
Posted
技术标签:
【中文标题】Web 配置转换不起作用【英文标题】:Web Config Transform not working 【发布时间】:2012-02-09 02:18:10 【问题描述】:在 .NET MVC 3.0 应用程序中,我在 appSettings
中有以下配置:
web.config
<appSettings>
<add key="SMTPHost" value="mail.domain.com"/>
<add key="SMTPUsername" value="user@gmail.com"/>
<add key="SMTPPort" value="25"/>
<add key="SMTPPwd" value="mypassword"/>
<add key="EmailFrom" value="notific@gmail.com"/>
</appSettings>
为了调试,我定义了以下配置转换:
web.Debug.config
<appSettings>
<add key="SMTPPort" value="58" xdt:Transform="Replace" xdt:Locator="Match(key)" />
</appSettings>
我在调试模式下运行应用程序,但我的 SMTP 端口仍然从web.config
获取值,而不是web.Debug.config
。
谁能建议这个配置有什么问题?
【问题讨论】:
【参考方案1】:Web.config 转换仅作为发布操作的一部分应用。
如果您希望将此作为app.config
构建操作的一部分完成,那么您可以使用 SlowCheetah - XML Transforms Visual Studio 插件:
http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5
【讨论】:
非常感谢您为我节省了很多时间。 哇,我花了 2 个小时才找到这个答案。感谢您发布它,我会一直把我的头发拉出来。 似乎在 Visual Studio 2015 中 (Web).config 转换 现在是内置功能,因此您不再需要 SlowCheetah。但内置转换仅在您发布应用程序时应用,而不是在您运行它时应用。你可以看看here我是怎么解决的。 不知道为什么要使用它,而@komsky 的回答提供了一个简单而干净的解决方案。 SlowCheetah 很棒,但从他们自己的文档来看:“对于 web 项目,当您发布或打包应用程序时,文件会被转换。”换句话说,不是在调试时。【参考方案2】:Visual Studio (2010 - 2019) 很遗憾 不 在您调试时直接支持它,它仅用于发布 - 即使它使用了扩展 SlowCheetah(标记答案)不适用于我(仅适用于使用 app.config 而不是 web.config 的项目)。
注意,有一个解决方法 described at codeproject。
它描述了如何修改 .msproj 文件以用转换后的版本覆盖当前的 web.config。
我将首先将该解决方法描述为 Option 1,但我最近发现了另一个 Option 2,它更易于使用(因此您可以向下滚动到 option 2如果你喜欢直接):
选项 1: 我添加了从原始 codeproject 文章 中获取的说明(请参阅上面的链接),因为那里的屏幕截图已经消失了,我没有'不想丢失全部信息:
在您开发和调试本地环境时,VS.Net 不会进行任何转换。但是,如果您愿意,可以采取一些步骤来实现这一点。
首先,在 VS.Net 中创建您想要的配置,假设默认的调试和发布不足以满足您的要求。 右键单击您的web.config
并选择添加配置转换 - 这将为您定义的每个配置创建一个依赖转换配置。
现在您可以将您的 web.config
重命名为 web.base.config
。
将web.config
添加到您的项目中。里面有什么并不重要,因为每次我们进行构建时它都会被覆盖,但我们希望它成为项目的一部分,所以 VS.Net 不会给我们 “你的项目未配置调试” 弹出窗口。
编辑您的 .csproj
项目文件,并将以下 TransformXml
任务添加到 AfterBuild 目标。在这里你可以看到我将使用web.[configuration].config
转换web.base.config
文件并将其保存为web.config
。详情请查看thisMicrosoft Q&A,有关如何扩展构建的说明请查看there。
选项 2:
基于this 的回答,我开发了一个简单的控制台应用程序TransformConfig.exe(C# 6.0 语法):
using System;
using System.Linq;
using Microsoft.Web.XmlTransform;
namespace TransformConfig
class Program
static int Main(string[] args)
var myDocumentsFolder = $@"C:\Users\Environment.UserName\Documents";
var myVsProjects = $@"myDocumentsFolder\Visual Studio 2015\Projects";
string srcConfigFileName = "Web.config";
string tgtConfigFileName = srcConfigFileName;
string transformFileName = "Web.Debug.config";
string basePath = myVsProjects + @"\";
try
var numArgs = args?.Count() ?? 0;
if (numArgs == 0 || args.Any(x=>x=="/?"))
Console.WriteLine("\nTransformConfig - Usage:");
Console.WriteLine("\tTransformConfig.exe /d:tgtConfigFileName [/t:transformFileName [/s:srcConfigFileName][/b:basePath]]");
Console.WriteLine($"\nIf 'basePath' is just a directory name, 'basePath' is preceeded.");
Console.WriteLine("\nTransformConfig - Example (inside PostBuild event):");
Console.WriteLine("\t\"c:\\Tools\\TransformConfig.exe\" /d:Web.config /t:Web.$(ConfigurationName).config /s:Web.Template.config /b:\"$(ProjectDir)\\\"");
Environment.ExitCode = 1;
return 1;
foreach (var a in args)
var param = a.Trim().Substring(3).TrimStart();
switch (a.TrimStart().Substring(0,2).ToLowerInvariant())
case "/d":
tgtConfigFileName = param ?? tgtConfigFileName;
break;
case "/t":
transformFileName = param ?? transformFileName;
break;
case "/b":
var isPath = (param ?? "").Contains("\\");
basePath = (isPath == false)
? $@"myVsProjects\" + param ?? ""
: param;
break;
case "/s":
srcConfigFileName = param ?? srcConfigFileName;
break;
default:
break;
basePath = System.IO.Path.GetFullPath(basePath);
if (!basePath.EndsWith("\\")) basePath += "\\";
if (tgtConfigFileName != srcConfigFileName)
System.IO.File.Copy(basePath + srcConfigFileName,
basePath + tgtConfigFileName, true);
TransformConfig(basePath + tgtConfigFileName, basePath + transformFileName);
Console.WriteLine($"TransformConfig - transformed 'basePath + tgtConfigFileName' successfully using 'transformFileName'.");
Environment.ExitCode = 0;
return 0;
catch (Exception ex)
var msg = $"ex.Message\nParameters:\n/d:tgtConfigFileName\n/t:transformFileName\n/s:srcConfigFileName\n/b:basePath";
Console.WriteLine($"TransformConfig - Exception occurred: msg");
Console.WriteLine($"TransformConfig - Processing aborted.");
Environment.ExitCode = 2;
return 2;
public static void TransformConfig(string configFileName, string transformFileName)
var document = new XmlTransformableDocument();
document.PreserveWhitespace = true;
document.Load(configFileName);
var transformation = new XmlTransformation(transformFileName);
if (!transformation.Apply(document))
throw new Exception("Transformation Failed");
document.Save(configFileName);
确保添加 DLL "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.XmlTransform.dll"
作为参考(此示例适用于 VS 2015,对于旧版本,将路径中的 v14.0
替换为适当的版本号,例如 v11.0
)。
对于 Visual Studio 2017,路径的命名架构已更改:例如,对于企业版,它位于此处:C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Microsoft\VisualStudio\v15.0\Web
。
我假设对于专业版,您需要将路径中的Enterprise
替换为Professional
。如果您使用的是预览版,请另外将2017
替换为Preview
。
以下是 Visual Studio 不同版本的路径如何更改的概述(如果您没有企业版,则可能需要将路径中的 Enterprise
替换为 Professional
):
VS 版本 路径(用于
Microsoft.Web.XmlTransform.dll
) 2015C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\Web
2017C:\Program Files (x86)\Microsoft Visual Studio\2017\
Enterprise\MSBuild\Microsoft\VisualStudio\v15.0\Web
2019C:\Program Files (x86)\Microsoft Visual Studio\2019\
Enterprise\MSBuild\Microsoft\VisualStudio\v16.0\Web
编译它并将.exe文件放入一个目录,例如C:\MyTools\
.
用法: 您可以在构建后事件中使用它(在项目属性中,选择构建事件,然后编辑构建后事件命令行)。命令行参数是(示例):
"C:\MyTools\TransformConfig.Exe" /d:Web.config /t:Web.$(ConfigurationName).config /s:Web.Template.config /b:"$(ProjectDir)\"
即首先是配置文件的名称,然后是转换配置文件,然后是可选的模板配置,然后是包含这两个文件的项目的路径。
我添加了可选的模板配置参数,因为否则您的原始完整配置将被转换覆盖,这可以通过提供模板来避免。
只需复制原始 Web.config 并将其命名为 Web.Template.config 即可创建模板。
注意:
如果您愿意,也可以将 TransformConfig.exe
文件复制到上述 Microsoft.Web.XmlTransform.dll
所在的 Visual Studio 路径,并在您需要转换配置的所有项目中引用它。
对于那些想知道我为什么添加 Environment.ExitCode = x;
分配的人:简单地从 Main 返回一个 int 对构建事件没有帮助。查看详情here.
如果您要发布项目并使用 Web.Template.config,请确保您在解决方案上使用正确的配置(通常是发布)进行了 重建你发布。原因是 Web.Config 在调试期间被覆盖,否则您可能最终会转换错误的文件。
【讨论】:
看起来 CodeProject 的帖子被坑了。他为他的代码示例使用了屏幕截图,现在自从他的博客关闭后,它们就被历史遗忘了。 是的,很遗憾,截图不见了。但至少文章文本仍然存在,描述了该方法。我已将文本描述添加到我的答案中以避免丢失。 是的,也许可以尝试联系 codeproject 的作者 James Coleman 来修复它。不过,不确定他是否还在那里活动。 @ThomasTeilmann 我认为这可能类似于丢失的屏幕截图中的内容。似乎达到了相同的基本结果。 ***.com/a/6437192/1003916【参考方案3】:回答你的问题并不简单,因为它提出了一个问题——如果你想用 Web.debug.config 转换 Web.config——转换效果应该存储在哪里?在 Web.config 本身?这将覆盖转换源文件!可能这就是 Visual Studio 在构建期间不进行转换的原因。
以前的 Matt 答案是有效的,但您可能希望将它们混合以获得通用解决方案,当您实际将活动解决方案配置从调试更改为发布等时可以使用。这是一个简单的解决方案:
-
为配置(调试、发布等)创建配置转换
将
Web.config
文件重命名为 Web.base.config
- 转换应自动重命名(Web.base.Debug.config
等)
将以下 transformWebConfig.proj XML 文件添加到您的项目文件夹:
<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="4.0" DefaultTargets="TransformWebConfig" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="TransformWebConfig">
<TransformXml Source="Web.base.config" Transform="Web.base.$(CurrentConfig).config" Destination="Web.config" />
</Target>
</Project>
-
导航到您的项目属性,选择构建事件并将以下内容添加到构建后事件命令行:
@if exist "%ProgramFiles(x86)%\MSBuild\12.0\bin" set PATH=%ProgramFiles(x86)%\MSBuild\12.0\bin;%PATH%
msbuild $(ProjectDir)transformWebConfig.proj /t:TransformWebConfig /p:CurrentConfig=$(ConfigurationName) /p:TargetProjectName=$(TargetPath)
现在,当您构建解决方案时,将创建一个 Web.config 文件,其中包含用于活动配置的有效转换。
【讨论】:
最干净和最好的答案。一些问题: 1. 为什么 XML 验证表明 TransformXml 元素在 Target 元素中无效? (构建工作顺便说一句)。 2.现在生成了真正的Web.Config,我还是把Web.Config添加到项目中。现在,每当我在调试/发布之间切换时,web.config 都会发生变化,但我不一定想一直将其提交到源代码库中。 1.无法真正说出 VS 如何使用架构验证此 XML,但此警告很常见,因此您可以忽略它。 2. 这取决于你使用的是什么仓库,但你可以例如使用 git.ignore 文件条目。 这对我来说效果很好——只是将 build-event 和 proj 文件中的 12 更改为当前版本。对于我使用的构建后事件:'"$(MSBuildBinPath)\msbuild.exe" $(ProjectDir)TransformWebConfig.proj /t:TransformWebConfig /p:CurrentConfig=$(ConfigurationName) /p:TargetProjectName=$(TargetPath)
并在 .proj 文件中将v12.0
更新为v14.0
。
对于 VS 2017,将每个 12.0
修改为 14.0
1)不要忘记将生成的web.config包含在web项目中,否则发布后不会复制到目标文件夹。 2)如果构建服务器缺少这两个文件,只需将它们复制到服务器“Microsoft.Web.Publishing.Tasks”,“Microsoft.Web.XmlTransform”【参考方案4】:
对于 VS 2017,我找到了答案 here 不确定为什么没有人在上面引用它,因为它似乎是一个非常流行的解决方案。也很容易。请确保您在 2019 年 3 月 5 日看到 IOrlandoni 的评论,以使其在 VS 2017 和所有版本中运行。
基本上它是一个两个步进器。首先,编辑 .csproj 文件,添加下面的代码。其次,您创建一个新的 web.base.config 配置并将现有的 web.config 复制到那里。之后,任何构建都会用您想要的转换覆盖您的 web.config。
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\WebApplications\Microsoft.WebApplication.targets" />
<Target Name="BeforeBuild">
<TransformXml Source="Web.Base.config"
Transform="Web.$(Configuration).config" Destination="Web.config" />
</Target>
【讨论】:
这可能是最好的答案,但 IMO 它缺少一个技巧。如果您将Web.config
从Content
更改为None
,那么您可以使用Source="Web.config" Destination="$(TargetPath).config"
(或者对于某些类型的项目,Destination="$(TargetDir)Web.config"
)。我还将转换移动到AfterBuild
,因为不再需要在复制文件之前完成它。
好的,实际上这不起作用,因为由于某种原因我无法将其配置为从 bin
运行。【参考方案5】:
您的直接问题已得到解答 - 解释是转换是在发布时应用的,而不是在构建时应用的。
但是,我认为它没有提供有关如何实现您想要做的事情的解决方案。
几天来,我一直在为这个确切的问题苦苦挣扎,寻找一种方法来保持 web.config 干净并在相应的转换文件中设置根据环境而变化的所有键。我的结论是,最简单和最稳定的解决方案是在原始 web.config 中使用调试值,这样当您在 Visual Studio 中进行调试运行时它们始终存在。
然后为您想要发布到的不同环境创建转换 - 测试、集成、生产 - 无论您拥有什么。现在内置的在发布时转换 web.config 文件的功能就足够了。无需 SlowCheetah 或编辑构建事件或项目文件。如果您只有网络项目。
如果您愿意,您还可以在解决方案中包含 web.debug.config 文件,只是为了保留一个单独的文件,其中包含与开发环境相关的所有值。请务必在其中注释,但在 Visual Studio 中运行时不会应用这些值,以防其他人尝试将其用于此目的!
【讨论】:
【参考方案6】:最近我在使用基于 .NET Framework 2.0 的旧 web.config 文件时遇到了同样的问题。解决方案是简单地删除 web.config 的命名空间(xmlns 属性在 configuration 根节点):
之前:<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
之后:<configuration>
【讨论】:
【参考方案7】:要在构建时完成转换:
从您的项目中排除 web.config (+ web.*.config)。 然后重命名磁盘上的文件如下
web.config => Web.Template.config web.Release.config => Web.Transform.Release.config web.Debug.config => Web.Transform.Debug.config将 web.config 添加到您的 gitignore 并提交到目前为止的更改。
最后,在文本编辑器中将以下内容添加到项目文件中。
<Target Name="BeforeBuild">
<TransformXml Source="Web.Template.config" Transform="Web.Transform.$(Configuration).config" Destination="Web.config" />
</Target>
<ItemGroup>
<Content Include="Web.config" />
<None Include="Web.*.config" />
</ItemGroup>
现在,只要您在 Visual Studio 中选择了调试配置,Web.Template.config 就会被 Web.Debug.Transform.config 转换为 Web.config。 Release 也是一样。
第一次生成 Web.config 时,您可能需要在构建后重新启动 Visual Studio,然后再次构建以让 Visual Studio 识别生成的 web.config。
此方法已在 Visual Studio 2019 上使用 ASP.NET(非核心)项目进行了测试。
【讨论】:
听起来很酷。会试一试 为我工作。谢谢【参考方案8】:显然有 Visual Studio 2015 的扩展
https://visualstudiogallery.msdn.microsoft.com/05bb50e3-c971-4613-9379-acae2cfe6f9e
此包使您能够根据构建配置转换您的 app.config 或任何其他 XML 文件
【讨论】:
SlowCheeta 不是新产品。它已经存在了很长时间。他们的 1.1 版本于 2011 年 9 月 8 日发布 @HaBo 感谢您的关注,我已将new
world 作为句子删除。【参考方案9】:
使用Octopus Deploy(社区版免费),让它为您转换web.config
。步骤:
-
Set up Octopus to deploy your web application
确保您的
Web.Release.config
的Build Action
属性设置为Content
,就像您的主要web.config
文件一样。
就是这样! Octopus 将在没有任何特殊配置的情况下完成其余的工作。默认的 IIS 网站部署将立即执行此操作:
【讨论】:
数字 2 是关键 :)【参考方案10】:添加到您的应用设置“xdt:Transform="Replace" 属性。 如下所示:
<appSettings xdt:Transform="Replace">
<add key="SMTPPort" value="58" xdt:Transform="Replace" xdt:Locator="Match(key)" />
</appSettings>
它将用调试配置替换整个 appsettings。但如果你不希望你可以应用任何你想要的标签。它将包括该标签的所有子元素。 顺便说一句,您还应该将属性设置为配置部分。我在下面标记:
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
【讨论】:
以上是关于Web 配置转换不起作用的主要内容,如果未能解决你的问题,请参考以下文章
Spring web:Java8 LocalTime 的@RequestBody Json 转换不起作用