With Visual Studio’s publish functionality you can conveniently preview how your web project behaves and looks like on your local IIS web server. With that said, I believe publishing makes sense only if you’ve done significant changes since, depending on how big your project is, it may take some time to sync your deployable project files with the web site root folder, and deploying new DLLs and config files will definitely restart your website and flush your caches.
But what if you just did a tiny update and just wanted to sync the changed file(s)? Well, you can hit F5 and enter the debug mode, or you can simply copy your changes directly into the IIS site’s location (I’ve seen developers do this). Not a big fan of either so I started looking into customizing my build targets so I can build-sync any update to my website project.
Build targets are nothing more than just a set of instructions that MSBuild follows in order to build your application. There are standard targets and we can always extend or override them as we see fit.
Importing the target file
First we’re gonna need to create a target file (let’s call it LocalBuild.targets), and import it in the asp.net web project – for this you’re gonna have to modify the .csproj file in a text editor. When you build your website project using MSBuild you can specify a parameter /p:DeployOnBuild=true which will try to publish your site. If this param is true we don’t want to import our LocalBuild.targets file, therefore, we need to set the Import condition to check if it will deploy upon build.
<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> … <!-- Add this to the bottom of the file --> <PropertyGroup> <WillDeployOnBuild>false</WillDeployOnBuild> <WillDeployOnBuild Condition="'$(DeployOnBuild.ToLower())' != 'false'">true</WillDeployOnBuild> </PropertyGroup> <Import Project="$(SolutionDir)Tools\BuildTargets\$(ProjectName)\LocalBuild.targets" Condition="!$(WillDeployOnBuild)" /> </Project>
Designing the target file
Let’s create a target called ‘UpdateLocalSite’ that will be called after the default Build target, which will then call targets that we will use to copy only the updated content files and binary files.
<?xml version="1.0" encoding="utf-8"?> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <LocalSiteDir> [Absolute path to your site root folder] </LocalSiteDir> </PropertyGroup> <Target Name="UpdateLocalSite" AfterTargets="Build"> <CallTarget Targets="CopyUpdatedContentFiles; CopyBinaries " /> </Target> <Target Name="CopyUpdatedContentFiles"> <Copy SourceFiles="@(Content)" DestinationFiles="@(Content->'$(LocalSiteDir)\%(RelativeDir)%(Filename)%(Extension)')" SkipUnchangedFiles="true" /> </Target> <Target Name="CopyBinaries"> <ItemGroup> <Binaries Include="$(OutputPath)\$(AssemblyName).dll" /> <Binaries Include="$(OutputPath)\%(Reference.Identity).dll" Condition="'%(Reference.HintPath)' == '' And Exists('$(ProjectDir)$(OutputPath)\%(Reference.Identity).dll')" /> <Binaries Include="%(Reference.HintPath)" Condition="'%(Reference.HintPath)' != ''" /> </ItemGroup> <Copy SourceFiles="@(Binaries)" DestinationFiles="@(Binaries->'$(LocalSiteDir)\bin\%(Filename)%(Extension)')" SkipUnchangedFiles="true" /> </Target> </Project>
With this target file in place we can see right away our changes integrated in our local site instance, hence, making testing a lot easier and development a lot faster.