Click here to Skip to main content
15,892,737 members
Articles / Programming Languages / C#
Tip/Trick

Copying linked content files using MSBuild

Rate me:
Please Sign up or sign in to vote.
4.71/5 (5 votes)
4 Jun 2015CPOL3 min read 26.6K   8   4
Sometimes we need to share JavaScript, CSS or images files amongst several web applications. This post shows how to do this using Visual Studio's linked files feature, combined with a simple MSBuild target to ensure the shared content files can be found by the browser.

Sharing files with Visual Studio's linked files

You may have a number of web applications that share one or more content files. For example, JavaScript libraries, or an image with the corporate logo. When such a shared file changes, you don't want to have to remember to copy the file to all the web applications.

A solution is to store the shared files in a central location, and then in Visual Studio add links to those files, rather than copying them. That way, Visual Studio always sees the latest version.

To create a link in Visual Studio:

  1. Right click on the directory where you want to add the link.
  2. Choose Add | Existing Item.
  3. In the file dialog, navigate to the directory with shared files and select the one you want.
  4. Open the drop down on the Add button (click the little down arrow) and choose Add As Link.

The shared file now appears in the Solution Explorer, with a "link" icon.

When you now edit a shared file, you'll find that the change is immediately visible in all web applications. If you keep the file in source control and you're using TFS rather than GIT, TFS will automatically check out the file when you change the file from any of the web applications.

Moreover, when you publish a web application, the shared files will be copied along with the other files of the site. Sweet!

Using an MSBuild target to physically copy the linked files

There is one problem though. When you hit F5 to debug the site, the browser can't find your linked shared files. This is because Visual Studio keeps a link to the shared file - it doesn't copy it to the directory where you placed the link in Solution Explorer.

The challenge now is to extend the build, so each time the project is built (by hitting F5 or otherwise), all linked files are copied to the directories where you placed the links. This way, you still automatically pick up changes to the shared files, while also making them available to the browser.

 To see how this is going to work, we'll need to have a look at how Visual Studio stores file links:

  1. Add a link to a file to your project if you haven't already done so.
  2. Open the .csproj file with your favorite text editor (Notepad will do).
  3. Find the file that you linked to - search for its name.

You'll find that whilst most content files have entries like this:

<Content Include="Scripts\jsnlog_test.js" />

File links look like this:

<Content Include="..\..\JSNLog\Scripts\jsnlog.js">
  <Link>Scripts\jsnlog\jsnlog.js</Link>
</Content>

In other words, their distinguishing feature is that they have a Link meta with the location where the file would have been had it been physically copied over.

This means that we can copy the linked files at each build by adding the following at the end of the .csproj file, just before the final </Project> tag:

<Target Name="CopyLinkedContentFiles" BeforeTargets="Build">
    <Copy SourceFiles="%(Content.Identity)" 
          DestinationFiles="%(Content.Link)" 
          SkipUnchangedFiles='true' 
          OverwriteReadOnlyFiles='true' 
          Condition="'%(Content.Link)' != ''" />
</Target>

This target uses BeforeTargets to ensure it is executed each time a build happens, even when no files in the project need to be built.

The Copy task uses a Condition to filter out all items in the Content item group that do not have a Link meta. This way, the copy is only applied to links. To speed up the process, it sets SkipUnchangedFiles to true, so if a linked file has not been changed, it won't be copied.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Australia Australia
Twitter: @MattPerdeck
LinkedIn: au.linkedin.com/in/mattperdeck
Current project: JSNLog JavaScript Logging Package

Matt has over 9 years .NET and SQL Server development experience. Before getting into .Net, he worked on a number of systems, ranging from the largest ATM network in The Netherlands to embedded software in advanced Wide Area Networks and the largest ticketing web site in Australia. He has lived and worked in Australia, The Netherlands, Slovakia and Thailand.

He is the author of the book ASP.NET Performance Secrets (www.amazon.com/ASP-NET-Site-Performance-Secrets-Perdeck/dp/1849690685) in which he shows in clear and practical terms how to quickly find the biggest bottlenecks holding back the performance of your web site, and how to then remove those bottlenecks. The book deals with all environments affecting a web site - the web server, the database server and the browser.

Matt currently lives in Sydney, Australia. He recently worked at Readify and the global professional services company PwC. He now works at SP Health, a global provider of weight loss web sites such at CSIRO's TotalWellBeingDiet.com and BiggestLoserClub.com.

Comments and Discussions

 
QuestionApplicable to Other Project Types? Pin
David A. Gray15-Jun-15 19:36
David A. Gray15-Jun-15 19:36 
AnswerRe: Applicable to Other Project Types? Pin
Matt Perdeck17-Jun-15 2:34
Matt Perdeck17-Jun-15 2:34 
GeneralRe: Applicable to Other Project Types? Pin
David A. Gray17-Jun-15 4:29
David A. Gray17-Jun-15 4:29 
Generalthanks Pin
Southmountain4-Jun-15 6:47
Southmountain4-Jun-15 6:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.