HaB*_*aBo 82 asp.net asp.net-mvc web-config web-config-transform slowcheetah
在.NET MVC 3.0应用程序中,我有以下配置appSettings:
<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>
Run Code Online (Sandbox Code Playgroud)
为了调试,我定义了以下配置转换:
<appSettings>
<add key="SMTPPort" value="58" xdt:Transform="Replace" xdt:Locator="Match(key)" />
</appSettings>
Run Code Online (Sandbox Code Playgroud)
我在调试模式下运行应用程序,但我的SMTP端口仍然从web.config,而不是web.Debug.config.
任何人都可以建议这种配置可能出错吗?
dev*_*tal 145
Web.config转换仅作为发布操作的一部分应用.
如果您希望将其作为app.config构建操作的一部分来完成,那么您可以使用SlowCheetah - XML Transforms Visual Studio插件:
http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5
Mat*_*att 23
不幸的是,Visual Studio(2010 - 2017)在调试时并不直接支持它,它只是用于发布 - 即使使用扩展名SlowCheetah(标记为答案)它也不适用于我(仅适用于使用app.config的项目而不是web.config中).
请注意,codeproject中描述了一种解决方法 .
它描述了如何修改.msproj文件以通过转换后的版本覆盖当前的web.config.
我将首先将该解决方法描述为选项1,但我最近发现了另一个选项2,它更易于使用(因此,如果您愿意,可以直接向下滚动到选项2):
选项1:我添加了原始代码项目文章中的说明(参见上面的链接),因为那里的屏幕截图已经消失,我不想丢失整个信息:
在开发和调试本地环境时,VS.Net不会进行任何转换.但是,如果您愿意,可以采取一些措施来实现这一目标.
web.config并选择Add Config Transforms - 这将为您定义的每个配置创建一个从属转换配置.web.config的web.base.config.web.config到您的项目.它并不重要,因为每次我们进行构建时它都会被覆盖但我们希望它是项目的一部分,所以VS.Net不会给我们"你的项目没有配置为调试" pop-起来..csproj项目文件并将以下TransformXml任务添加到AfterBuild目标.在这里你可以看到我将web.base.config使用web.[configuration].config它来转换文件,它将保存为web.config.有关详情,请查看这个微软Q&A,以及指导如何扩展构建,看看那里.选项2:
根据这个答案,我开发了一个简单的控制台应用程序,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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
确保将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.
编译它并将.exe文件放入目录中,例如C:\MyTools\.
用法: 您可以在post build事件中使用它(在项目属性中,选择Build Events,然后编辑Post-build事件命令行).命令行参数是(示例):
"C:\ MyTools\TransformConfig.Exe"/d:Web.config /t:Web.$(ConfigurationName).config /s:Web.Template.config/b:"$(ProjectDir)\"
即首先是配置文件的名称,然后是转换配置文件,后跟可选的模板配置,后跟包含两个文件的项目路径.
我添加了可选的模板配置参数,因为否则您的原始完整配置将被转换覆盖,这可以通过提供模板来避免.
只需复制原始Web.config并将其命名为Web.Template.config即可创建模板.
注意:
如果您愿意,还可以将TransformConfig.exe文件复制到上面提到的Visual Studio路径中,Microsoft.Web.XmlTransform.dll并在需要转换配置的所有项目中引用它.
对于那些想知道为什么我添加了Environment.ExitCode = x;赋值的人:简单地从Main返回一个int对构建事件没有帮助.详情请见此处.
如果您要发布项目并且正在使用Web.Template.config,请确保在发布之前使用正确的配置(通常是Release)对解决方案进行了重建.原因是在调试期间会覆盖Web.Config,否则您最终可能会转换错误的文件.
kom*_*sky 21
回答你的问题并不简单,因为它带来了一个问题 - 如果你想与Web.debug.config改造的Web.config - 在转型效果应该储存在哪里?在Web.config本身?这会覆盖转换源文件!可能这就是为什么Visual Studio在构建期间不进行转换的原因.
以前的Matt答案是有效的,但您可能希望将它们混合在一起,以便在您实际将活动解决方案配置从调试更改为发布等时使用通用解决方案.这是一个简单的解决方案:
Web.config文件Web.base.config- 转换应自动重命名(Web.base.Debug.config等)<?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>
Run Code Online (Sandbox Code Playgroud)
@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)
Run Code Online (Sandbox Code Playgroud)
现在,在构建解决方案时,将创建一个Web.config文件,其中包含有效配置的有效转换.
对于 VS 2017,我在这里找到了答案,不确定为什么没有人在上面引用它,因为它似乎是一个非常受欢迎的解决方案。也很容易。请确保您在 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>
Run Code Online (Sandbox Code Playgroud)
小智 5
您的直接问题已得到解答 - 解释是转换应用于发布,而不是构建。
但是,我认为它没有提供有关如何实现您想要做的事情的解决方案。
几天来,我一直在为这个确切的问题而苦苦挣扎,寻找一种方法来保持 web.config 干净,并在相应的转换文件中设置因环境而异的所有键。我的结论是,最简单和最稳定的解决方案是在原始 web.config 中使用调试值,这样当您在 Visual Studio 中进行调试运行时,它们始终存在。
然后为您想要发布到的不同环境创建转换 - 测试、集成、生产 - 无论您拥有什么。现在用于在发布时转换 web.config 文件的内置功能就足够了。无需 SlowCheetah 或编辑构建事件或项目文件。如果您只有 Web 项目。
如果您愿意,您还可以在您的解决方案中包含 web.debug.config 文件,只是为了保留一个单独的文件,其中包含与开发环境相关的所有值。请务必在其中注释,但在 Visual Studio 中运行时不会应用这些值,以防其他人尝试将其用于该目的!