Web.config的Build与Release转换不起作用

29

我有一个ASP.NET Web应用程序项目,通过Entity Framework连接到远程数据库。在调试期间(例如在本地计算机上运行项目时),与数据库的IP地址不同于发布后(例如在Web服务器上上传项目并从浏览器运行它时)。直到现在,我总是手动更改Web.config文件中的数据库连接字符串以在两者之间进行切换(基本上我有两个连接字符串,一个命名为'Debug',另一个命名为'Release',每当我部署时我只需交换名称)。

现在我刚刚注意到可以通过Web.config Transformation Syntax自动完成此操作,在Web.Release.config版本中放置修改后的连接字符串,然后在Release配置下构建DLL时应该使用它。

然而,这对我似乎不起作用...

这是常规Web.config文件的相关部分(其中包含本地使用的Debug连接字符串):

<?xml version="1.0"?>
<configuration>

  <connectionStrings>
    <!-- Debug connection string. Release connection string is in Web.Release.config file -->
    <add name="DatabaseEntities" connectionString="A" providerName="System.Data.EntityClient" />
  </connectionStrings>

</configuration>

这里是Web.Release.config文件,根据示例,如果DLL处于Release模式下,则应将“DatabaseEntities”连接字符串“A”替换为“B”:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">

  <!-- Replace the DatabaseEntities connection string with the Release version (local IP address) -->
  <connectionStrings>
    <add name="DatabaseEntities"
      connectionString="B"
      xdt:Transform="Replace" xdt:Locator="Match(name)"/>
  </connectionStrings>

</configuration>

(显然,"A"和"B"只是我真实连接字符串的占位符)

当我调试应用程序时(例如,只需按下F5),将使用默认的Web.config,并且我可以访问数据库。 然后,我通过配置管理器将生成配置更改为发布。 解决方案中的所有项目都设置为发布配置。 然后我构建解决方案(仅通过Build或甚至通过完整重建(例如,清理,重建))。 我将新构建的DLL上传到Web服务器,以及Web.config和Web.Release.config文件,当我尝试访问数据库时,我无法访问它,因为它仍在尝试通过调试IP地址访问数据库,因此找不到...

似乎Web.Release.config文件完全被忽略了,或者至少没有替换连接字符串。

我做错了什么? 转换语法有误吗? 我没有正确地在发布模式下构建应用程序吗?


这有时可能会有点棘手,如果您设置错误了一个选项,它就无法正常工作。如果您能添加 Configuration Manager 的屏幕截图,我们可能会发现您忽略的一些东西。 - Shai Cohen
这篇文章对我很有帮助:https://dev59.com/JnA75IYBdhLWcg3wboYz。 - Victor F
6个回答

51
然后我构建解决方案(仅通过构建或者完整重建),上传新构建的DLL到Web服务器,以及Web.config和Web.Release.config文件。
你的错误在于:如果仅仅构建解决方案,那么Web配置转换不会对本地环境起作用,你需要发布。
你的部署过程似乎有些奇怪:你只是复制了DLLs、Web.config和web.Release.config。在我的看来,你复制了源代码而不是编译好的应用程序。发布的Web应用程序不包含web.release.config。
你应该发布你的项目(右键单击Web应用程序->发布)到本地文件系统,并从那里复制文件,或者使用你选择的其他部署方法。
2年前,我写了一篇关于web.config转换的文章。它为VS 2010提供了一个逐步教程(在VS 2012中,发布对话框发生了变化): http://www.tomot.de/en-us/article/5/asp.net/how-to-use-web.config-transforms-to-replace-appsettings-and-connectionstrings

17
有没有办法在构建/按F5时进行转换?这将使生活更轻松。 - Erick T
你可以尝试为Build.PublishSelection分配一个快捷方式,以节省一些鼠标点击。 - citronas
1
我只需将其发布到我的C:/Publish文件夹,然后设置我想要测试发布设置的数据库。您可以在windows/system32/drivers/etc/hosts文件设置中设置请求“127.0.0.1 published”,并在IIS中设置一个应用程序(http://published)。然后随时进行发布和测试。 - jwize
@Erick T:https://dev59.com/questions/mnA65IYBdhLWcg3w1SNC? - ossek

4

在您的csproj文件中,您可以添加一个操作,在每次构建之前执行并执行web.config变换:

<Target Name="BeforeBuild">
    <TransformXml Source="web.config" Transform="web.$(Configuration).config" Destination="web.config" />
</Target>

随着VS2022的这个改变,我们不再需要添加Slow Cheeta包或插件。 - Grappachu

3

3
我认为转换只在发布网站/应用程序时才完成。 在构建应用程序时不会进行转换。后者将不断更改源代码控制下的web.config(这将是真正的麻烦)。

1
如果只有连接字符串在web.config转换期间没有被覆盖,那么我所做的就是:清除“发布Web”向导中“设置”部分中“在运行时使用此连接字符串”的复选框。这个设置会覆盖连接字符串的web.config转换。

0

这很灵活,你应该能够进行一些微调以应用自定义转换构建(而无需发布)

我们在我们的(Windows服务)项目中实现了这一点,在构建时应用转换

您需要修改项目文件并添加类似以下内容

在这里,我们告诉msbuild在完成编译后应用转换,但仅当条件为真时(请参见https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild-conditions?view=vs-2017

请注意,我们正在使用构建属性(自定义的msbuild属性)“Env”,例如msbuild ... /p:Env=Prod将导致App.Prod.config

<UsingTask TaskName="TransformXml" AssemblyFile="C:\Some\Path\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterCompile" Condition="Exists('some condition')">
  <!--Generate transformed app config in the intermediate directory-->
  <TransformXml Source="App.config" Destination="$(IntermediateOutputPath)$(TargetFileName).config" Transform="App.$(Env).config" />
  <!--Force build process to use the transformed configuration file from now on.-->
  <ItemGroup>
    <AppConfigWithTargetPath Remove="App.config" />
    <AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config">
      <TargetPath>$(TargetFileName).config</TargetPath>
    </AppConfigWithTargetPath>
  </ItemGroup>
</Target>

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