ASP.net Web Application Project directory structure - asp.net

I've recently converted an ASP.net 2.0 Web Site Project to an ASP.net 3.5 Web Application Project and I'm still getting used to the way the files are structured.
The problem I'm running into is that when I build the corresponding Web Deployment Project it copies the obj directory. But its my understanding that the obj directory is just intermediary and doesn't provide any useful purpose for a deployed website right?
If that is correct, is there some way to configure the Web Application Project to put the intermediary obj directory elsewhere, or is there something else I should be doing to handle this properly?

Just add in the .csproj_deploy file the following
<Target Name="AfterBuild">
<Message Text="------ Deleting unwanted files ------" Importance="high" />
<CreateItem Include="$(OutputPath)obj">
<Output TaskParameter="Include" ItemName="ObjDirPattern"/>
</CreateItem>
<RemoveDir Directories="#(ObjDirPattern)">
<Output TaskParameter="RemovedDirectories" PropertyName="objdir" />
</RemoveDir>
<Message Text="Deleted obj directory: $(objdir)" Importance="high" />
</Target>
For more see http://msdn.microsoft.com/en-us/library/7z253716.aspx

Related

AspNetCompiler task in SharePoint project

I would like to know how to compile aspx files after build in a sharepoint solution to see the run-time errors, e.g. missing resource (when translating thep page using resources).
When I add the AspNetCompiler task into my csproj like this (only showing the end of the project file):
...
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\SharePointTools\Microsoft.VisualStudio.SharePoint.targets" Condition="'$(VSToolsPath)' != ''" />
<Target Name="AfterBuild">
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(ProjectDir)" />
<!-- ToolPath="C:\Windows\Microsoft.NET\Framework64\v2.0.50727" -->
</Target>
<PropertyGroup>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
</Project>
, then when building the project I get the following error in the aspx file:
Could not load file or assembly '$SharePoint.Project.AssemblyFullName$' or one of its dependencies. The system cannot find the file specified.
Obviously the asp compiler tries to build the aspx files in the project directory which do not have the tokens replaced. However, I was unable to finalise the task so it would operate on fiels with the tokens replaced. My knowledge of MSBuild is limited which might be the problem.
The only way to do the token replacement is to create the wsp package because the replacement occurs there. The solution is then to create the wsp, unpack it to a target folder, create a new directory there called "bin", move the dlls to the bin directory and then run aspnet compiler on the target folder. The whole process can be done in MSBUild (csproj) file. This is my solution - at the end of the csproj file, after the sharepoint targets are imported:
<Import Project="$(VSToolsPath)\SharePointTools\Microsoft.VisualStudio.SharePoint.targets" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup>
<!-- schedule creating the package in the build, the task is defined in sharepoint targets -->
<BuildDependsOn>$(BuildDependsOn);CreatePackage</BuildDependsOn>
<PostBuildEvent>
</PostBuildEvent>
<!-- define file/folder properties -->
<ExpandDest>$(TargetDir)_wsp</ExpandDest>
<WspBinPath>$(ExpandDest)\bin</WspBinPath>
<WspPath>$(TargetDir)MyProject.wsp</WspPath>
</PropertyGroup>
<!-- override "after build" target, it must depend on the package creation,
which ensures that the target runs after we have the wsp package ready -->
<Target Name="AfterBuild" DependsOnTargets="CreatePackage">
<!-- create the folder where we unpack our wsp -->
<MakeDir Directories="$(ExpandDest)" />
<!-- use expand to unpack the wsp -->
<Message Text="$(ExpandWsp)" Importance="high" />
<Exec Command="expand "$(WspPath)" -F:* "$(ExpandDest)"" />
<!-- create the "bin" folder -->
<MakeDir Directories="$(WspBinPath)" />
<!-- move all dlls and xmls from the root to the bin folder -->
<Exec Command="move /Y "$(ExpandDest)\*.dll" "$(WspBinPath)"" />
<Exec Command="move /Y "$(ExpandDest)\*.xml" "$(WspBinPath)"" />
<!-- run the aspnet compiler on the wsp folder,
the tool path param ensures that .net 2 compiler will be used,
we need that because we compile sharepoint 2010 which is .net 3.5
and the latest aspnet compiler for .net 3.5 is in .net 2 -->
<AspNetCompiler
VirtualPath="/"
PhysicalPath="$(ExpandDest)"
Clean="true"
ContinueOnError="false"
ToolPath="C:\Windows\Microsoft.NET\Framework\v2.0.50727" />
</Target>
</Project>
EDIT: The process is a bit more complicated. According to your own project, you have to move some files to specific folders. Basically, follow what you are told by the compiler.
As you probably know required files are already copied (as part of the packaging process in Visual Studio) to a folder before creating the wsp file and you can easily point to that folder thus no need to do all those folder creation, moving and extraction. So the best solution IMHO would be to use only the following:
<Target Name="AfterBuild" DependsOnTargets="CreatePackage">
<Message Text="Validating Asp.Net files (PhysicalPath: $(LayoutPath), ToolPath: $(FrameworkDir)$(FrameworkVersion))..." Importance="high" />
<AspNetCompiler
VirtualPath="/"
PhysicalPath="$(LayoutPath)"
Clean="true" ContinueOnError="false"
ToolPath="$(FrameworkDir)$(FrameworkVersion)" />
<Message Text="Asp.Net validation is complete" Importance="high" />

How to get aspnet_compiler invoked from Visual Studio during build?

I want Visual Studio to precompile my ASP.NET application which is used as an Azure web role payload. So I've found this post that explains how to call aspnet_compiler to validate views.
I tried to add the following to "post-build event" of my ASP.NET application:
call "%VS100COMNTOOLS%\vsvars32.bat"
aspnet_compiler -v / -p $(ProjectDir)
or alternatively this (application name specified explicitly):
call "%VS100COMNTOOLS%\vsvars32.bat"
aspnet_compiler -v /ASP.NET-Application-ProjectNameHere -p $(ProjectDir)
In both cases when the build runs I see the following in the build output:
Setting environment for using Microsoft Visual Studio 2010 x86 tools.
Utility to precompile an ASP.NET application
Copyright (C) Microsoft Corporation. All rights reserved.
and clearly no precompilation happens because if I change any .aspx or .cshtml file "Build Action" to "None" it doesn't get to the Azure service package and the view no longer opens once the package is deployed to Azure.
How do I setup aspnet_compiler for precompiling from within Visual Studio?
If you want to use Asp.NET Compiler within your Visual Studio / msbuild then you can add
AspNetCompiler Task to your project file (.csproj/.vbproj) and set MvcBuildViews to true.
Example:
<Project>
<PropertyGroup>
<MvcBuildViews>true</MvcBuildViews>
</PropertyGroup>
<!-- ... -->
<Target Name="PrecompileWeb" AfterTargets="build" Condition="'$(MvcBuildViews)'=='true'">
<Message Text="Starting AspNetCompiler for $(ProjectDir)" Importance="high" />
<AspNetCompiler
VirtualPath="temp"
PhysicalPath="$(WebProjectOutputDir)"
Force="true"
/>
</Target>
<!-- ... -->
</Project>
You may also set TargetPath attribute to specify destination directory.
AfterTargets="build" is similar to "post-build event". See Target Build Order for more.
Integrate ASPX compilation into Visual Studio
One of the principles I insist on is to always try my build on a clean environment and simulate installation as if it was done by QA. Lately I've noticed that I keep falling on errors hidden deep in the aspx files. So, why not using the old and familiar aspnet_compiler.exe tool? It is located at C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 and it is quite easy to use.
As a VS add-ins freak I've started thinking on an amazing add-in that will integrate to the VS and will listen to build events and display the results at the output pane. Heck, why not add some coffee serving capabilities?
It took me about 10 minutes of googling to stumble on this blog. Mike Hadlow had a genius in its simplicity idea. Use the POST BUILD EVENT!
All I need to do is put the following line in the post build event: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_compiler.exe -v / -p "$(ProjectDir)\"
Now, All that is left is to make the process of adding this line to each and every web project in our team to be automatic.
I have just the add-in for that :)
enter link description here
The answer from Matej was helpful for me, but I was not able to use it as-is and still get it to work for both local builds within Visual Studio and automated builds via TFS.
I had to add some extra msbuild settings. Actually, there were 2 different scenarios that I had. One project was an Web App that built into the _PublishedWebsites folder and one was an MVC Web App that did not build into the _PublishedWebsites folder.
First, add the following if it is not already in your project file:
<PropertyGroup>
<MvcBuildViews>true</MvcBuildViews>
</PropertyGroup>
For the one WITH _PublishedWebsites:
<Choose>
<When Condition="'$(BuildingInsideVisualStudio)' == true">
<PropertyGroup>
<AspNetCompilerPhysicalPath>$(ProjectDir)</AspNetCompilerPhysicalPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<AspNetCompilerPhysicalPath>$(WebProjectOutputDir)</AspNetCompilerPhysicalPath>
</PropertyGroup>
</Otherwise>
</Choose>
<Target Name="PrecompileWeb" AfterTargets="build" Condition="'$(MvcBuildViews)'=='true'">
<!-- aspnet_compiler.exe needs to be run on the folder that has the aspx files and the "bin" subfolder.
When running locally, the value needs to be the project directory, which is $(ProjectDir).
When running the TFS build, the value needs to be (BuildFolder)\(ProjectName)\_PublishedWebsites\(ProjectName).
The $(AspNetCompilerPhysicalPath) will hold the correct value for both types of builds.
-->
<Message Text="Starting AspNetCompiler for $(ProjectName) at $(AspNetCompilerPhysicalPath)" Importance="high" />
<AspNetCompiler
VirtualPath="/"
PhysicalPath="$(AspNetCompilerPhysicalPath)"
TargetPath="$(AspNetCompilerPhysicalPath)\bin_precompile"
Force="true"
/>
</Target>
For the one WITHOUT _PublishedWebsites:
<Choose>
<When Condition="'$(BuildingInsideVisualStudio)' == true">
<PropertyGroup>
<AspNetCompiler_CopyFilesFirst>false</AspNetCompiler_CopyFilesFirst>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<AspNetCompiler_CopyFilesFirst>true</AspNetCompiler_CopyFilesFirst>
</PropertyGroup>
<ItemGroup>
<AllOutputFiles Include="$(OutDir)\\**\*.*" />
</ItemGroup>
</Otherwise>
</Choose>
<Target Name="PrecompileWeb" AfterTargets="build" Condition="'$(MvcBuildViews)'=='true'">
<!-- aspnet_compiler.exe needs to be run on the folder that has the cshtml files and the "bin" subfolder. I could not find a setting that was appropriate for both.
When running locally, the value needs to be the project directory, which is $(ProjectDir).
When running the TFS build, there is no folder that matches both of those criteria.
So first we will copy the output into the source code folder's "bin" subfolder,
then run it against the source $(ProjectDir), the same as if we were building locally.
-->
<Message Text="Before running AspNetCompiler, copy files from $(OutDir) to $(ProjectDir)\bin" Importance="high" />
<Exec Command="( robocopy.exe /mir $(OutDir) $(ProjectDir)\bin ) ^& IF %25ERRORLEVEL%25 LEQ 1 exit 0" Condition="'$(AspNetCompiler_CopyFilesFirst)'=='true'" />
<Message Text="Starting AspNetCompiler for $(ProjectName) at $(ProjectDir)" Importance="high" />
<AspNetCompiler
VirtualPath="/"
PhysicalPath="$(ProjectDir)"
TargetPath="$(ProjectDir)\bin_precompile"
Force="true"
/>
</Target>

How do you specify a direct build name directory using TFS build of an ASP.net web application?

I have a TFS build set up to deploy an ASP.net project to a test server.
The build works great, and deploys to the test server fine, but instead of putting it into the \Website directory that my IIS webserver is configured for, it puts the build into \Website_20100511.6
Why is the date suffixed to the directory name? Is there a way to turn that off so I can publish directly to the \Website?
You don't want to have the build agent build to the actual location your site is running from. You need to add script to the end of the build process (tfsbuild.proj file) to take the code from the drop location and move it to the web server.
Something like this:
<Target Name="AfterDropBuild">
<Message Text="PortalFilesToPublish location is $(DropLocation)\$(BuildNumber)" Importance="Low" />
<CreateItem Include="$(DropLocation)\$(BuildNumber)\Default\_PublishedWebsites\MyWebPortal\**\*.*" Exclude="*.pdb" >
<Output ItemName="PortalFiles" TaskParameter="Include" />
</CreateItem>
<Copy
SourceFiles="#(PortalFiles)"
DestinationFiles="#(PortalFiles ->'\\testserver.test.lab\Test Lab\MyWebPortal\%(RecursiveDir)%(Filename)%(Extension)')"
ContinueOnError="true" />
</Target>

ASP.NET MVC 1.0 AfterBuilding Views fails on TFS Build

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?
Actually, there's a better solution to this problem. I've tested it with VS/TFS 2010 but it should also work with VS/TFS 2008.
<Target Name="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
</Target>
I'm going to work with the MVC team to update their project template to to use this approach along with a custom target (rather than overriding AfterBuild).
I've published a blog post on How to Turn on Compile-time View Checking for ASP.NET MVC projects in TFS Build 2010.
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.
Jim Lamb's solution didn't work for us when I built our web .csproj with
/p:UseWPP_CopyWebApplication=true;PipelineDependsOnBuild=False
because the target was being executed AfterBuild and the application has not been copied into the WebProjectOutputDir yet. (BTW, I pass those properties to the web project build cos I want the build to create a OutDir folder with only my binaries and cshtml files suitable for zipping, ie not an in-place build)
To get around this issue and honour the intent of his original target, I did the following:
<PropertyGroup>
<OnAfter_WPPCopyWebApplication>
MvcBuildViews;
</OnAfter_WPPCopyWebApplication>
</PropertyGroup>
<Target Name="MvcBuildViews" Condition="'$(MvcBuildViews)'=='true'">
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
</Target>
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>
....
This problem seems similar to the one talked about here:
http://blogs.msdn.com/aaronhallberg/archive/2007/07/02/team-build-and-web-deployment-projects.aspx
it seems the invocation of aspnet_compiler.exe fails to locate the binaries because the are not in the bin folder of the MVC project on the build machine. I haven't worked out a solution yet.
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.

How can I deploy an ASP.NET web application using Team Build?

I have managed to install Team Foundation Server 2008 and I created a separate build server (which works because my builds are currently failing).
I have created a simple "Hello World" Web application (all is the standard Default.aspx page) and have it in TFS's source control system.
Previously, prior to TFS, I'd simply precompile my web application and xcopy the results on to a pre-created IIS Virtual directory.
Scouring Google for a while, I have yet to find a step by step guide on correctly deploying an application from TFS Source via TeamBuild to a designated test web server. I know MS Build falls into this equation, so any guidance would be helpful.
I have seen bits and pieces about deployments, with folders such as _PublishedWebSites mentioned, but have yet to find anything step by step.
I've had success using a exec task in the AfterDropBuild target in the TFSBuild.proj file.
<Target Name="AfterDropBuild>
<Exec Command="xcopy /Y /E "$(DropLocation)\\$(BuildNumber)\%(ConfigurationToBuild.FlavorToBuild)\_PublishedWebsites\MyWebsite1\*.*" "\\server\MyWebsite1\"" />
<Exec Command="xcopy /Y /E "$(DropLocation)\\$(BuildNumber)\%(ConfigurationToBuild.FlavorToBuild)\_PublishedWebsites\MyWebsite2\*.*" "\\server\MyWebsite2\"" />
</Target>
Note that the permissions need to be setup correctly for the TFS service user to access the folder on the server your are copying to.
Firstly you should be using WebDeployment projects as this will do a lot more compilation and checking of your code and markup. See here for more info.
I have 4 environments setup DV [Development], PY [Prototype], PP [Pre-Production], PD [Production] all matching branches in TFS. Each of these has also has an entry in the sln configuration manager where you can setup what projects are required to be build and the build flags.
Once that is setup correctly you can then start setting up deployment scripts. I prefer use MSbuild to deploy as it will give you a lot more fine-grained approach to deployment. MSbuild is a bit strange to start with however once you get the hang of it it's quite powerful.
My deployment script which is added to the TeamBuild config is below. Basically as you can see I do a bit of post-build cleanup before I copy to the live servers. I also use 2 MSbuild frameworks (imported at the top).
<Import Project="$(MSBuildExtensionsPath)\Microsoft\SDC Tasks - Release 2.1.3155.0\Microsoft.Sdc.Common.tasks"/>
<Import Project="$(MSBuildExtensionsPath)\FreeToDev\MSBuild Tasks Suite 3.5\FreeToDev.MSBuild.tasks"/>
<PropertyGroup>
<InetpubFolder>\\PathToInetPub</InetpubFolder>
<AppFolder>AppFolder</AppFolder>
<AppFolderPath>$(InetpubFolder)$(AppFolder)</AppFolderPath>
<WebDeployName>WebDeployProjectName</WebDeployName>
<Debug>0</Debug>
<AppConfiguration>DV</AppConfiguration>
</PropertyGroup>
<Target Name="AfterDropBuild">
<Message Text="Begin Release to $(AppConfiguration) Webserver" />
<Message Text="DropLocation = $(DropLocation)" />
<CallTarget Targets="PostBuildCleanUp" />
<CallTarget Targets="DeployApp" />
</Target>
<Target Name="DeployApp">
<GetBuildProperties TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)">
<Output TaskParameter="DropLocation" PropertyName="DropLocation"></Output>
</GetBuildProperties>
<PropertyGroup>
<CodeDropLocation>$(DropLocation)\$(AppConfiguration) Release</CodeDropLocation>
</PropertyGroup>
<ItemGroup>
<AppFilesToDelete Include="$(AppFolderPath)\**\*.*" Exclude="$(AppFolderPath)\Library\*.*;$(AppFolderPath)\App_Offline.htm;$(AppFolderPath)\jobs\**\*.*" />
</ItemGroup>
<ItemGroup>
<FilesToDeploy Include="$(CodeDropLocation)\$(AppFolder)\**\*.*" Exclude="" />
</ItemGroup>
<Copy SourceFiles="$(CodeDropLocation)\$(AppFolder)\App_Offline[RemoveToActivate].htm" DestinationFiles="$(AppFolderPath)\App_Offline.htm" OverwriteReadOnlyFiles="true"/>
<Message Text="Deleting files in $(AppFolderPath)" />
<Microsoft.Sdc.Tasks.File.DeleteFiles Files="#(AppFilesToDelete)" Force="true" Condition="$(Debug)==0" />
<Message Text="Copy $(CodeDropLocation)\$(AppFolder) to $(AppFolderPath)" />
<Copy Condition="$(Debug)==0" SourceFiles="#(FilesToDeploy)" DestinationFiles="#(FilesToDeploy->'$(AppFolderPath)\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="true"/>
<Message Text="Deploy to $(AppConfiguration) Completed" />
<Microsoft.Sdc.Tasks.File.DeleteFiles Files="$(AppFolderPath)\App_Offline.htm" Force="true" />
<OnError ExecuteTargets="ErrorHandler" />
</Target>
<Target Name="ErrorHandler">
<Message Text="Error encountered!!" />
</Target>
<Target Name="PostBuildCleanUp">
<GetBuildProperties TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)">
<Output TaskParameter="DropLocation" PropertyName="DropLocation"></Output>
</GetBuildProperties>
<PropertyGroup>
<CodeDropLocation>$(DropLocation)\$(AppConfiguration) Release</CodeDropLocation>
</PropertyGroup>
<ItemGroup>
<PostBuildCleanUpFilesToDelete Include="$(CodeDropLocation)\*.*;$(CodeDropLocation)\bin\*.xml;$(CodeDropLocation)\bin\*.pdb"/>
</ItemGroup>
<RemoveDir Directories="$(CodeDropLocation)\_PublishedWebsites\Web" />
<Microsoft.Sdc.Tasks.File.DeleteFiles Files="#(PostBuildCleanUpFilesToDelete)" Force="true">
<Output TaskParameter="DeletedFiles" ItemName="FilesThatWereDeleted" />
</Microsoft.Sdc.Tasks.File.DeleteFiles>
<Message Text="The files that were removed were #(FilesThatWereDeleted)" />
<FTDFolder TaskAction="Move" Path="$(CodeDropLocation)\_PublishedWebsites\$(WebDeployName)" TargetPath="$(CodeDropLocation)\$(AppFolder)"/>
<RemoveDir Directories="$(CodeDropLocation)\_PublishedWebsites" />
<RemoveDir Directories="$(CodeDropLocation)\$(AppFolder)\WebDeploy" />
<OnError ExecuteTargets="ErrorHandler" />
</Target>
Obviously you will need to modify to your system setup. Also it clears down the target folder before it starts to copy the new build accross. This is to make sure they system is clean but obviously you will need to add anything that you need to keep to the ExcludedFiles list.
I also have a folder for each environment in the main application project. This holds the web.config replacements (another feature of WebDeployment projects) and any other environement specifc files.
It will be a long process to get it working correctly but hopefully this will get you started!! (Obviously if you choose this apporach!)
This can be done via the build scripts directly, the Vertigo Software guys usually are the best source of info for a lot of TFS questions like this...unfortunately their blog posts don't usually rank that high on google. This one's by Jeff Atwood, one of the creators of this site:
Copying Web Files After a Team Build

Resources