_bin_deployableAssemblies and MSBuild

If you’re deploying a MVC 3 website to a server without MVC 3 in the GAC, you need to include the proper dlls in the bin folder.

Phil Haack blogged about a new feature in Visual Studio that allows you to easily include the required assemblies with your deployment without having to reference all of the required assemblies directly.

http://haacked.com/archive/2011/05/25/bin-deploying-asp-net-mvc-3.aspx

Apparently, the new _bin_deployableAssemblies folder only works correctly if you’re publishing your website from within Visual Studio. If you’re using TFS to build and publish your site, you’ll need to use a customized target.

<Target Name="CopyBinDeployableAssemblies" AfterTargets="CopyFilesToOutputDirectory" Condition="Exists('$(MSBuildProjectDirectory)\_bin_deployableAssemblies')">
    <ItemGroup>
        <_binDeployableAssemblies Include="$(MSBuildProjectDirectory)\_bin_deployableAssemblies\**\*.*" />
        <FilesForPackagingFromProject Include="%(_binDeployableAssemblies.Identity)">
            <DestinationRelativePath>bin\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
        </FilesForPackagingFromProject>
    </ItemGroup>

    <Copy SourceFiles="@(_binDeployableAssemblies)" DestinationFolder="$(OutDir)%(RecursiveDir)" SkipUnchangedFiles="true" />
    <Copy Condition="'$(WebProjectOutputDir)' != ''" SourceFiles="@(_binDeployableAssemblies)"	DestinationFolder="$(WebProjectOutputDir)\bin\%(RecursiveDir)" SkipUnchangedFiles="true"/>
</Target>

This target is set to follow CopyFilesToOutputDirectory. Its 4 steps ensure that the contents of your _bin_deployableAssemblies folder end up in both the drop folder specified in TFS, and in the website after your project is packaged and deployed.

The steps are as follows:

  • Look for all files in the _bin_deployableAssemblies folder:
    <_binDeployableAssemblies Include="$(MSBuildProjectDirectory)\_bin_deployableAssemblies\**\*.*" />
  • Include the found files in the item used for website publishing:
    <FilesForPackagingFromProject Include="%(_binDeployableAssemblies.Identity)">
        <DestinationRelativePath>bin\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
    </FilesForPackagingFromProject>
  • Copy the files to the build’s output folder:
    <Copy SourceFiles="@(_binDeployableAssemblies)" DestinationFolder="$(OutDir)%(RecursiveDir)" SkipUnchangedFiles="true" />
  • Copy the files to the website output folder:
    <Copy Condition="'$(WebProjectOutputDir)' != ''" SourceFiles="@(_binDeployableAssemblies)"	DestinationFolder="$(WebProjectOutputDir)\bin\%(RecursiveDir)" SkipUnchangedFiles="true"/>

You can include the new target at the end of your project file, or you can add it to a new .targets file and include that file in your MVC site’s project file like so:

<Import Project=".\TFS.BinDeployableAssemblies.targets" />

The path is relative to your project file.

If you do choose to create a separate targets file, be sure to wrap your target in the appropriate project element:

<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Target Name="CopyBinDeployableAssemblies" ... >	
        ...
    </Target>
</Project>
Advertisements
This entry was posted in Deployment. Bookmark the permalink.

One Response to _bin_deployableAssemblies and MSBuild

  1. Nice workaround. I worked quite a bit with TFS Build at my last job, and hit a couple scenarios where it seemed like web projects weren’t designed well to cooperate with CI servers. In particular, I think it was non-trivial to get web.config replacements (stock in VS 2010) to work. It would work when you built and published locally, but I had to call some hokey target to get it to work with TFS Build.

Thoughts?

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s