Wednesday, 10 October 2012

Deploying Non Project Files with Web Deploy

Deploying Websites and Web Applications has changed massively over the years, I have seen the likes of FTP, Copy & Paste over RDP (why!!) etc but there has always been a degree of, did I copy the correct files, did I miss any, did I upload the correct client config etc.

Since VS2010 I have been a big fan of always publishing my applications to either a local folder and then upload or directly to the server, depending on the setup.

One thing I have always struggled with is publishing files that aren't part of my project, and ensuring the correct client config settings are uploaded. Now I'm running VS2012 full time I decided it was time to put to bed these issues and ensure I could use one click, or as near to one as possible, to deploy stage configurations of my applications as well as live.

VS2012 has tweaked publishing again, it now includes a much fuller publish model, with WebDeploy amongst the usual FTP, FileSystem etc. The Package / Publish process is just an extension of MSBuild, which means you can perform any process / action that you would normally do with MSBuild, this could mean perform minimization / compression of css / js etc. Other people have written about this, http://sedodream.com/2011/02/25/HowToCompressCSSJavaScriptBeforePublishpackage.aspx

When you deploy MSBuild performs two steps, first of all it bundles all your content into a temporary location and then copies it all to the final location, or compiles a package if that's what you have configured

What I needed to do was alter the process to pull in some additional files into the temporary location so that they then get published to the final place.

This is possible by extending the PipelineCollectFilesPhaseDependsOn phase. We can simply add a build target to our file and then run this in the PipelineCollectFilesPhaseDependsOn phase.

Our Target:


<Target Name="CopyIOCFiles">
    <Message Text="Copy IOC Files" Importance="high"/>
    <ItemGroup>
      <_CustomFiles Include="$(ProjectDir)\IOC\**\*" />
      <FilesForPackagingFromProject  Include="%(_CustomFiles.Identity)">
        <DestinationRelativePath>bin\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
      </FilesForPackagingFromProject>
    </ItemGroup>
  </Target>

It's worth noting here that my target could just contain the ItemGroup element however I like to know the target has run so by sticking in a message element we know it's ran by looking at our build output,

This target is then run in the correct phase via the following:


 <PropertyGroup>
    <PipelineCollectFilesPhaseDependsOn>
      CopyIOCFiles;
      $(PipelineCollectFilesPhaseDependsOn);
    </PipelineCollectFilesPhaseDependsOn>
  </PropertyGroup>

Hurrah! That's it, actually a lot easier than I thought, when you combine this with web.config transformations on a per configuration basis you really can deploy one application in several configurations in one click.



4 comments:

  1. Excellent information. This site definitely explains essential concepts to its readers. Thanks for continuing to write such wonderful articles.

    Web Developer

    ReplyDelete
  2. Thanks for posting this tip - much appreciated!

    ReplyDelete
  3. This is a very essential for me as well. I must follow the discussion which is very attractive to me as well. Keep it up. It is a wonderful article which is very essential for me as well. Keep it up.

    Daniel

    ReplyDelete
  4. Excellent article, thanks for this awesome tip.

    Thanks!

    ReplyDelete