使用Visual Studio的web.config转换进行调试

166

可能重复:
如何在内置的Visual Studio调试器服务器中使用Web.debug.config?

我想要使用在发布时正常工作的Web.config转换来进行调试。

当我发布Web应用程序时,Visual Studio会根据当前的构建配置自动转换Web.config。 如何告诉Visual Studio在开始调试时执行相同的操作? 在调试启动时,它仅使用默认的Web.config而没有进行转换。

有任何想法吗?


21
这个问题不是一个重复。链接的“重复”https://dev59.com/JnA75IYBdhLWcg3wboYz指的是特定版本的Visual Studio。这个问题没有指定版本,而且在我看来,这个问题有更多有用的答案。 - Peter Wone
5个回答

100

了解到web.debug.configweb.release.config仅用于打包/发布。我已找到一种方法来实现你想要的功能,并在我的博客中介绍了它,链接为:https://devblogs.microsoft.com/aspnet/asp-net-web-projects-web-debug-config-web-release-config/

现在我们来看看如何实现问题提问者想要的功能。

简单概括一下,当他在特定配置上进行构建时,他希望将一个特定的转换应用于web.config。所以,显然不希望维护一个web.config文件,因为它将被覆盖。

我们需要做的是创建一个新文件web.template.config,它只是web.config的副本。然后通过Windows资源管理器删除web.config(不要使用Visual Studio删除,因为我们不希望从项目中删除它)。

注意:如果您使用的是集成在Visual Studio中的源代码控制提供程序,则可能需要从源代码控制中删除web.config。

此外,我们不想使用web.debug.configweb.release.config,因为它们已在Web发布管道中具有明确定义的角色,所以我们不想扰乱它。相反,我们将创建两个新文件,与项目和web.template.config位于同一文件夹中,即web.dev.debug.configweb.dev.release.config

这些文件的想法是,在使用Visual Studio进行调试或运行应用程序时将应用这些转换。现在,我们需要连接到生成/打包/发布过程中,来实现这一切。对于Web应用程序项目(WAP),可以创建一个名为{ProjectName}.wpp.targets的项目文件,与项目名称相同,放置在同一文件夹中,作为可扩展性点。如果此文件与WAP位于同一文件夹中,则将自动导入到项目文件中。因此,我创建了该文件,并放置了以下内容:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <!-- Make sure web.config will be there even for package/publish -->
  <Target Name="CopyWebTemplateConfig" BeforeTargets="Build">
    <Copy SourceFiles="web.template.config"
          DestinationFiles="web.config"/>
  </Target>
  
  <PropertyGroup>
    <PrepareForRunDependsOn>
      $(PrepareForRunDependsOn);
      UpdateWebConfigBeforeRun;
    </PrepareForRunDependsOn>
  </PropertyGroup>

  <!-- This target will run right before you run your app in Visual Studio -->
  <Target Name="UpdateWebConfigBeforeRun">
    <Message Text="Configuration: $(Configuration): web.dev.$(Configuration).config"/>
    <TransformXml Source="web.template.config"
              Transform="web.dev.$(Configuration).config"
              Destination="web.config" />
  </Target>

  <!-- Exclude the config template files from the created package -->
  <Target Name="ExcludeCustomConfigTransformFiles" BeforeTargets="ExcludeFilesFromPackage">
    <ItemGroup>
      <ExcludeFromPackageFiles Include="web.template.config;web.dev.*.config"/>
    </ItemGroup>
    <Message Text="ExcludeFromPackageFiles: @(ExcludeFromPackageFiles)" Importance="high"/>
  </Target>
</Project>

让我稍微解释一下。我创建了一个名为CopyWebTemplateConfig的目标,它将始终复制web.template.configweb.config,即使您没有在Visual Studio中调试应用程序。

这是必要的,因为我们仍然需要支持Visual Studio的包/发布过程。然后,我扩展了属性PrepareForRunDependsOn,将UpdateWebConfigBeforeRun目标包括其中。该属性用于识别在从Visual Studio运行任何托管项目之前需要执行的目标列表。

在此目标中,我使用TransformXml任务来转换web.template.config,使用正确的web.dev.***.config文件。之后,您的应用程序将使用基于您的构建配置的正确web.config启动。 之后,我有另一个目标ExcludeCustomConfigTransformsFiles,通过属性BeforeTargets="ExcludeFilesFromPackage"注入到包/发布过程中。这是必要的,因为当应用程序被打包或发布时,我们不希望包括这些文件。 所以,这就是全部内容。

为了更好地解释这种情况下的包/发布过程。当您打包/发布时,将仍然使用web.debug.configweb.release.config(取决于构建配置)。但是最终它正在转换的文件是web.template.config,因此您可能需要根据该文件中包含的内容进行调整。有问题/评论吗?


2
Mike,我之前也遇到了同样的问题。但是,当我删除了<Target Name="CopyWebTemplateConfig" />节点后,它就按照我需要的方式工作了。 - Nick Spiers
9
了解 *.wpp.targets 文件比了解转换实现更有价值。我已经寻找类似的东西有一段时间了。 - kenchilada
3
贡献非常重要。然而,实际尝试后,我发现关于保留web.debug.config和web.debug.release但不包含web.config文件在解决方案中的说明(它需要被包含)非常令人困惑。此外,变换也无法正常工作?使用“慢速猎豹”,f5 > transform > run,也完全误导了,因为f5绑定的是调试而不是编译。 - brumScouse
3
你的解决方案很复杂,因为你试图绕过IISExpress在项目文件夹中运行网站的事实,而你又不能进行转换,因为输出会破坏源web.config。与其使用web.template.config这种脆弱且不友好于IDE的方法,不如改变方式:按下F5时部署到一个文件夹,启动IISExpress来提供该文件夹的服务,并像往常一样连接到IISExpress。 - Peter Wone
6
如果你使用的是Visual Studio的较新版本并遇到了这个问题,我需要告诉你如何解决。你需要将以下内容进行修改:将<Target Name="CopyWebTemplateConfig" BeforeTargets="Build">改为<Target Name="CopyWebTemplateConfig" BeforeTargets="PrepareForBuild">然后问题就会解决了。 - Matti Price
显示剩余15条评论

38

安德鲁正在走上正确的道路。当您使用此功能时,它的设计方式如下。

web.config 这是开发人员应在本地使用的配置文件。理想情况下,您应该将其标准化。例如,您可以将 localhost 用于 DB 字符串等。您应该努力使其在开发机器上无需更改即可正常工作。

web.debug.config 这是在将应用程序发布到开发暂存环境时应用的转换。这将更改为目标环境所需的 web.config。

web.release.config 这是在将应用程序发布到“生产”环境时应用的转换。显然,根据您的应用程序/团队,您必须小心密码。

转换当前正在运行的 web.config 的问题在于,转换可能对 web.config 执行破坏性操作。例如,它可能会删除属性、删除元素等。


4
在本地运行应用程序时,切换Release和Debug模式一直会产生影响。如果你希望进行转换以使其成为规则的例外,则这反直觉。 - AaronLS
19
你说的是正确的,但在我看来,该功能的设计存在一定局限性。对于任何规模的团队,所有开发人员都使用标准化的web.config可能并不可行(除非是最简单的情况)。而且,在我的观点中,该功能没有为本地构建提供支持是一个很大的遗憾。 - MemeDeveloper
4
此外,为什么转换的破坏性本质存在问题呢?web.config和转换应该都在SC中。每个需要不同配置的环境都应该有自己的转换,例如web.config、web.devgroup1.config、web.devgroup2.config、web.staging.config、web.production.config等。因此,尽管web.config会发生变化,但不会丢失任何内容,进行“获取最新版本+构建”将为该环境生成正确的web.config,不会有任何损失。 - MemeDeveloper
2
我同意 @MemeDeveloper 的观点,即在团队内所有开发人员都使用标准化的 web.config 是完全不现实的。微软应该创建一种解决方案,允许开发人员在 web.config 中拥有自己的设置,而不会影响到源代码控制中检查的 web.config。 - Mick
2
当你有相应的配置激活时,这些配置转换在调试器中没有被应用是很疯狂的。正如AaronLS所说,这是一个非常违反直觉的规则例外。 - Triynko
显示剩余3条评论

27

你可以使用“默认”web.config作为你的开发/调试版本,而web.release.config显然仍然是发布版本,因为它的变换是在发布时应用的。


46
在多人开发环境中,这种方法并不总是有效(比如,考虑连接字符串)。 - Ben Collins
3
与Ben的观点非常相似,不妨考虑使用多个开发环境。我使用三台不同的开发电脑,测试不同的浏览器等,经常需要更改各种配置以针对这些不同的设置。 - MemeDeveloper
6
有时我需要针对集成或暂存数据库进行调试,而不是通常的开发数据库。在运行 VS 的调试器时应用适当的转换将非常有帮助。 - Zarepheth
4
@BenCollins说得对。目前情况是,每当你需要为调试目的更改连接字符串时,你都需要实际更改web.config文件。除非你记得在提交之前还原更改,否则可能会导致源代码控制中web.config文件不必要的修订。如果在构建时应用web.debug.config文件,则可以简单地忽略此文件而不必担心web.config文件上的多余修订,从而允许开发人员自定义其配置。 - Mick
2
这是一个相当懒惰的回答,我正在一个多开发环境中工作,这种方法行不通。 - Simon Price

19

在您的调试配置中,添加一个构建后步骤,并使用它来替换/转换您的 web.config


如果由于某些原因,你无法执行我的答案建议的操作,这是我认为的次佳选择。我认为预/后构建任务有时会被忽视! - Andrew Barber
1
由于这意味着您将覆盖原始的 web.config,请确保您不会永久丢失最终需要的设置。要知道这实际上正在做什么。任何 web.Debug.configweb.config 进行的永久转换,您必须确保您的 web.Release.config 修复所有问题。 - Doug S
1
相关文章:https://gist.github.com/EdCharbeneau/9135216 - Suamere

15
尽管我赞同最简单的方法通常是最好的,但我可以很容易地想象,在某段时间内,您希望将IDE连接到测试数据库而不是开发数据库。虽然您可以在默认的web.config文件中指定开发连接字符串,但如果有一个Web.Test.config文件,那将会非常好,这样当您将构建配置切换为“Test”时,在您的IDE中仍然可以自动获取新的设置。
历史上的替代方案是注释掉一个连接字符串集合,换句话说,这些新的配置转换有希望终结这种丑陋的做法。尽管一个默认的开发文件和一个发布转换可能在大多数情况下都可行,但在我看来,将后置构建步骤添加到转换web.config文件是更完整的答案。

4
后置生成事件中将web.config转换的语法是什么? - Cutter
你可以使用命令来复制一个单独的文件;一种是用于调试/测试,另一种是用于生产(以确保发布版本不会包含测试信息)。 - Andrew Barber
我同意。在调试云项目时,配置的工作方式就是这样。如果像类库等其他部分一样有一些一致性,例如配置转换,那将会很好。 - Jonas Stensved
我在 Web 服务中使用不同的数据库进行调试和发布。看看我的解决方案:它对我很有效: https://dev59.com/JnA75IYBdhLWcg3wboYz#30357289 - Mickey Mouse

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接