ASP.NET MVC 1.0 AfterBuilding 视图在 TFS 构建上失败

Posted

技术标签:

【中文标题】ASP.NET MVC 1.0 AfterBuilding 视图在 TFS 构建上失败【英文标题】:ASP.NET MVC 1.0 AfterBuilding Views fails on TFS Build 【发布时间】:2010-10-19 19:56:37 【问题描述】:

我已从 ASP.NET MVC Beta 升级到 1.0,并对 MVC 项目进行了以下更改(如 RC 发行说明中所述):

<Project ...>
  ...
  <MvcBuildViews>true</MvcBuildViews>
  ...
  <Target Name="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
    <AspNetCompiler VirtualPath="temp" PhysicalPath="$(ProjectDir)\..\$(ProjectName)" />
  </Target>
  ...
</Project>

虽然构建在我们的本地开发盒上运行良好,但它在 TFS 2008 构建下失败并显示“无法加载类型 'xxx.MvcApplication'”,请参阅下面的构建日志:

...
using "AspNetCompiler" task from assembly "Microsoft.Build.Tasks.v3.5, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
Task "AspNetCompiler"

  Command:
  C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_compiler.exe -v temp -p D:\Builds\xxx\Continuous\TeamBuild\Sources\UI\xxx.UI.Dashboard\\..\xxx.UI.Dashboard 
  The "AspNetCompiler" task is using "aspnet_compiler.exe" from "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_compiler.exe".
  Utility to precompile an ASP.NET application
  Copyright (C) Microsoft Corporation. All rights reserved.

/temp/global.asax(1): error ASPPARSE: Could not load type 'xxx.UI.Dashboard.MvcApplication'.
  The command exited with code 1.

Done executing task "AspNetCompiler" -- FAILED.
...

MVC 1.0 安装在 TFS 上,解决方案在同一 TFS 服务器上的 Visual Studio 实例中构建时编译。

如何解决此 TFS 构建问题?

【问题讨论】:

【参考方案1】:

其实,这个问题有更好的解决方案。我已经使用 VS/TFS 2010 对其进行了测试,但它也应该适用于 VS/TFS 2008。

<Target Name="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
  <AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
</Target>

我将与 MVC 团队合作更新他们的项目模板,以使用此方法和自定义目标(而不是覆盖 AfterBuild)。

我已经发表了一篇关于如何Turn on Compile-time View Checking for ASP.NET MVC projects in TFS Build 2010 的博文。

【讨论】:

应该可以很好地处理多个 Web 项目 - 每个项目的 WebProjectOutputDir 都是不同的。 这最终成为我们使用的解决方案。谢谢吉姆!它已在 ASP.NET MVC 3 工具更新中得到修复。在此处查看我的博客文章:haacked.com/archive/2011/05/09/… 跟进:我似乎需要你的目标块的这个修改版本: [抱歉格式化] 在 VS 2017 中使用 MVC 5 执行此操作的最佳方法是什么?这些都不起作用。 答案中的链接不再起作用:(你有正确的吗?【参考方案2】:

问题源于这样一个事实,即在 ASP.NET MVC 项目的 AfterBuild 目标中使用的 AspNetCompiler MSBuild 任务期望引用 Web 项目的 bin 文件夹中的 dll。

在桌面构建中,bin 文件夹是您在源代码树下所期望的位置。

但是,TFS Teambuild 会将源代码的输出编译到构建服务器上的不同目录。当 AspNetCompiler 任务启动时,它找不到 bin 目录来引用所需的 DLL,并且您得到了异常。

解决方法是将MVC项目的AfterBuild目标修改为如下:

  <Target Name="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
    <AspNetCompiler Condition="'$(IsDesktopBuild)' != 'false'" VirtualPath="temp" PhysicalPath="$(ProjectDir)\..\$(ProjectName)" />
    <AspNetCompiler Condition="'$(IsDesktopBuild)' == 'false'" VirtualPath="temp" PhysicalPath="$(PublishDir)\_PublishedWebsites\$(ProjectName)" />
  </Target>

此更改使您能够在桌面和 TFS 构建服务器上编译视图。

【讨论】:

那行得通。希望 MS 相应地更改 .csproj 文件模板。 这太疯狂了,为什么他们还没有解决这个问题!! ?? 我会与 TFS TeamBuild 团队核实,但我不确定我们是否可以“修复”这个问题。这个答案硬编码了一个 TFS 特定的目录结构“_PublishedWebsites”。如果您不使用 TFS TeamBuild 来构建您的网站,而是使用其他东西怎么办?那很可能会破裂。通过将此构建移动到 TFS Team Build,您已经自定义了您的项目。您需要相应地更新路径,这就是回答此问题的人所做的。 我在下面的回答中详细介绍了解决此问题的更好方法。 Jim 的解决方案是我们在 ASP.NET MVC 3 Tools Update 中使用的解决方案。请参阅我对他的回答的评论。【参考方案3】:

当我使用

构建我们的 web .csproj 时,Jim Lamb 的解决方案对我们不起作用
/p:UseWPP_CopyWebApplication=true;PipelineDependsOnBuild=False

因为目标正在执行AfterBuild,而应用程序尚未复制到WebProjectOutputDir。 (顺便说一句,我将这些属性传递给 Web 项目构建,因为我希望构建创建一个 OutDir 文件夹,其中仅包含适合压缩的二进制文件和 cshtml 文件,即不是就地构建)

为了解决这个问题并尊重他最初目标的意图,我做了以下事情:

<PropertyGroup>
    <OnAfter_WPPCopyWebApplication>
        MvcBuildViews;
    </OnAfter_WPPCopyWebApplication>
</PropertyGroup>

<Target Name="MvcBuildViews" Condition="'$(MvcBuildViews)'=='true'">
    <AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
</Target>

【讨论】:

【参考方案4】:

我假设您的意思是您更改了 .csproj 文件中的以下设置:

<MvcBuildViews>true</MvcBuildViews>

不应触及您在问题中发布的设置。 如果它可以在您的本地机器上运行,那么显然您可以预先构建一个 ASP.NET MVC 应用程序。

我认为您需要了解您的 TFS 构建环境和本地 VS 机器之间的不同之处。也许它正在使用不同版本的 MsBuild 或其他东西。

尝试使用详细输出执行两个构建,并比较两者以查看有什么不同。

【讨论】:

TFS 中使用的路径等似乎与我的本地计算机和源代码管理中的路径完全不同,因此您必须为每个场景指定不同的位置。 @haacked 为什么这个模板从来没有更新过?当你第一次遇到它时,它相当混乱。尤其是所有那些不习惯处理此类事情的“TFS Basic”新用户【参考方案5】:

我们仍在对此进行测试,但您似乎可以将标签集中的 false/true 移动到您的 DEBUG 构建版本的属性组中,您仍然可以将其设置为 true 并且 MSBuild 将编译(假设 MSBuild TfsBuild.proj 文件设置为使用除调试配置以外的其他内容)。您需要使用记事本编辑 csproj 文件来完成此操作。

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <MvcBuildViews>true</MvcBuildViews>
    ....

您需要将 MVCBuildViews 标记从上面的默认属性组移动到调试配置属性组(下面)。同样,当我们获得 TFS / MSBuild 设置时,我将尝试将我们添加到 TFS 中的 TFSBuild.proj 文件中的步骤发布。

  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <MvcBuildViews>true</MvcBuildViews>
    <DebugSymbols>true</DebugSymbols>
    ....

【讨论】:

【参考方案6】:

这个问题似乎与这里讨论的问题相似: http://blogs.msdn.com/aaronhallberg/archive/2007/07/02/team-build-and-web-deployment-projects.aspx 似乎调用 aspnet_compiler.exe 无法找到二进制文件,因为它们不在构建机器上 MVC 项目的 bin 文件夹中。我还没有找到解决方案。

【讨论】:

【参考方案7】:

接受的答案对我不起作用。 $(PublishDir) 参数未指向正确的位置。相反,我不得不使用:

  <Target Name="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
    <AspNetCompiler Condition="'$(IsDesktopBuild)' != 'false'" VirtualPath="temp" PhysicalPath="$(ProjectDir)\..\$(ProjectName)" />
    <AspNetCompiler Condition="'$(IsDesktopBuild)' == 'false'" VirtualPath="temp" PhysicalPath="$(OutDir)\_PublishedWebsites\$(ProjectName)" />
  </Target>

【讨论】:

好吧,只要答案为您指明了正确的方向,那么一切都很好。我的设置中的 OutDir 指向包含解决方案中其他项目的所有程序集的根构建目录,PublishDir 指向解决方案中包含的 Web 应用程序项目。您的解决方案是否包含除 MVC Web 应用程序之外的其他项目? 是的,它包含多个项目,是的,您的回答确实为我指明了正确的方向。我不确定为什么 $PublishDir 适合你而不是我,但我并没有太挂断它,修复很简单,我只是想如果其他人遇到同样的问题我会把它放在那里.【参考方案8】:

我的源代码管理中有一些旧文件夹在解决方案中不可见。

【讨论】:

【参考方案9】:

您不能预先构建 ASP.NET MVC 应用程序。

【讨论】:

以上是关于ASP.NET MVC 1.0 AfterBuilding 视图在 TFS 构建上失败的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET MVC 1.0 AfterBuilding 视图在 TFS 构建上失败

Orchard 发布1.0版本和ASP.NET MVC 3 RTM

如何将项目引用添加到 ASP.NET Core 1.0 MVC 项目

ASP.NET Core 1.0 基础与应用启动

Asp.net: WebForm基础上构建Mvc的方法

asp.net mvc2.0重写MvcHandler