ASP.NET MVC 1.0 AfterBuilding Views fails on TFS Build

Viewed 14153

I've upgraded from ASP.NET MVC Beta to 1.0 and did the following changes to the MVC project (as descibed in the RC release notes):

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

While the build runs fine on our local dev boxes, it fails under TFS 2008 Build with "Could not load type 'xxx.MvcApplication'", see below build log:

...
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 is installed on TFS and the solution compiles when built within a Visual Studio instance on the same TFS server.

How can I resolve this TFS Build issue?

9 Answers

The problem stems from the fact that the AspNetCompiler MSBuild task used within the AfterBuild target of an ASP.NET MVC project expects to reference the dll's in the bin folder of the Web project.

On a desktop build the bin folder is where you would expect it under your source tree.

However TFS Teambuild compiles the output of your source to a different directory on the build server. When the AspNetCompiler task starts it cannot find the bin directory to reference the required DLL and you get the exception.

Solution is to modify the AfterBuild target of the MVC Project to be as follows:

  <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>

This change enables you to compile Views on both the desktop, and the TFS build server.

I assume you meant you changed the following setting in the .csproj file:

<MvcBuildViews>true</MvcBuildViews>

The setting you posted in your question shouldn't be touched. If it works on your local machine, then obviously you can pre-build an ASP.NET MVC application.

I think you need to track down what's different between your TFS build environment and your local VS machines. Maybe it's using a different version of MsBuild or something.

Try performing both builds with verbose output and compare the two to see what's different.

We are still testing this out, but it appears that you can move the false/true from the tag set, into the property group for your DEBUG build version, you can still set it to true and MSBuild will compile (assuming MSBuild TfsBuild.proj file is setup to use something other than debug configuration). You will need to edit the csproj file using Notepad to accomplish this.

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

You need to move the MVCBuildViews tag from the default property group above, to the debug configuration property group (below). Again, when we get the TFS / MSBuild setup, I'll try to post the step we added to our TFSBuild.proj file in TFS.

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

The accepted answer didn't work for me. The $(PublishDir) parameter did not point to the correct location. Instead I had to use:

  <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>

I had some old folders in my source control that were not visible in the Solution.

You cannot pre-build an ASP.NET MVC application.

Related