Developing ASP.NET IIS Applications: Triggering LiveReload on a successful Visual Studio or MSBuild build

I’m all about getting rid of the friction in development. All that ‘ceremony’ that ends up built into your muscle memory to get your projects built and running.

One bit of small friction, but one you pay regularly, is pressing F5 in web applications, reloading the page after you’ve changed the source code. LiveReload is a really nice solution to that when you’re editing JavaScript and HTML, and in ASP.NET MVC when you’re editing Razor (CSHTML) files.

However, the job isn’t all done, and when you’re making server-side changes — changing controllers and such — LiveReload isn’t as easy to make fire. You really want it to trigger when it finishes a build, once all your binaries are up to date. I decided to fix that with a very small MSBuild target. The idea is that you add this into your web app (manually stitching it into your CSPROJ file) and when you build your source, it writes a small random file to disk. You use LiveReload to watch for that file, and that will trigger your browser to refresh. It’s a small — very small — improvement to your workflow if you’re already using LiveReload, but it’s something you do so often that any time you can get rid of a tiny piece of friction, you save yourself a little bit of the mental capacity you use for concentrating on real problems. In a very real way, each little bit of friction steals an IQ point or two; hoard them for the difficult tasks! As Alfred North Whitehead said:

“It is a profoundly erroneous truism, repeated by all copy-books and by eminent people when they are making speeches, that we should cultivate the habit of thinking of what we are doing. The precise opposite is the case. Civilization advances by extending the number of important operations which we can perform without thinking about them. Operations of thought are like cavalry charges in a battle — they are strictly limited in number, they require fresh horses, and must only be made at decisive moments.” – ANW

You need to get LiveReload into your workflow. I’ve found the best for me is to use Grunt or Gulp, both of which are designed to work with LiveReload. On windows, it’s been the most reliable way for me to get it to run — the original app is an alpha version, there’s not been an update in a long time, and I’ve found it flakey.

So here’s what you need to do;

Make sure you’ve got node.js installed

Come on now. Get it if you haven’t already. Nodejs.

Create a package.json file in your solution directory.

If you don’t already have a package.json file, open a command window, change directory to your solution folder, and type

npm init

And hit ‘enter’ a bunch of times.  The defaults are fine, but you may need to type your project name in, in lower case, if it complains about your folder name.

Install Grunt and Grunt-Contrib-Watch

Now install Grunt, the task runner, and Grunt-Contrib-Watch, a package which watches for file changes and triggers useful work.


npm install -g grunt-cli
npm install grunt --save-dev
npm install grunt-contrib-watch --save-dev

Nice and straightforward!

Create a Gruntfile

In your Solution directory, create a file called Gruntfile.js. (Note the capitalisation.) Then add this to it;

module.exports = function(grunt) {

var reloadTokens = ['{{MyWebProjectFolder}}\LiveReloadOnSuccessfulBuild.token']

grunt.initConfig({
  watch: {
    files: reloadTokens,
    options: {
      livereload: true,
    }
  }
});

grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', ['grunt-contrib-watch']);

};

Alter the file — you’ll see on the second line the token {{MyWebProjectFolder}} which you should replace with the relative folder path from your solution to your web application folder. Normally that’s the name of the project in Visual Studio. This is the config file that tells Grunt to watch for a file called ‘LiveReloadOnSuccessfulBuild.token’, a file that gets generated by a little bit of MSBuild trickery you’ll see in a minute. This file needs to go into source control.

Create the MSBuild target file

In your web application folder — the same folder that holds your CSPROJ file — create a file called LiveReloadOnSuccessfulBuild.targets and put in this content;

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <ItemGroup>
 <!-- trick from https://blogs.msdn.microsoft.com/msbuild/2005/10/06/how-to-add-a-custom-build-action-to-visual-studio/ -->
 <AvailableItemName Include="UpdateOnSuccessfulBuild" />
 </ItemGroup>

<Target Name="LiveReloadOnSuccessfulBuild" AfterTargets="Build">
 <!-- If you're using LiveReload, you want your pages to reload 
 after your web app compiles. This add a build action, 
 "UpdateOnSuccessfulBuild", which you can use to mark a 
 dummy file. The build action writes a random guid to 
 the file within your web app folder; this can be watched 
 for in your Gruntfile.js, gulpfile.js, or by the 
 LiveReload app. -->
 <Message Importance="High" Text="Writing LiveReload token to LiveReloadOnSuccessfulBuild.token" />
 <WriteLinesToFile
 File="LiveReloadOnSuccessfulBuild.token"
 Lines="Live Reload Token: this changes on a successful build, to trigger LiveReloads. Exclude from source control! $([System.Guid]::NewGuid().ToString())"
 Overwrite="true"
 Encoding="Unicode"/>
 </Target>
</Project>

This is an MSBuild file — the same stuff that runs when you build your solution — and it instructs the build process to create a file called ‘LiveReloadOnSuccessfulBuild.token’ whenever the build completes. The Gruntfile I described earlier watches for this file, and when it finds it, it sends a signal to LiveReload to reload your page. This needs to go into source control.

Wire up the targets file into your web app build process

We need to wire this targets file up into visual studio’s build system. Open your web application’s CSPROJ file in a text editor, and on the penultimate line, just above </Project>, put this;


 <Import Project="$(ProjectDir)LiveReloadOnSuccessfulBuild.targets" />

Save the file, and if prompted in visual studio, allow it to reload your web app.

That’s all the editing done. Now, when you build in Visual Studio, it will alter the ‘LiveReloadOnSuccessfulBuild.token’ file and put something like this in;


Live Reload Token: this changes on a successful build, to trigger LiveReloads. Exclude from source control! ad7c25b3-dcfa-4571-98d9-ad9936c1e1d8

 

As it says, you may want to make sure this file isn’t checked into source control — if you’re using TFS, you don’t need to do anything, but if you’re using git, you may want to put it in your .gitignore file.

Install LiveReload extension in Chrome

When LiveReload works the way it does it is to watch your files, and when a change is made, it sends a signal. But what listens for the signal? You need to install an extension in Chrome.

use it!

OK, so we’re almost there. With a command window open in your solution directory, enter

grunt watch

That is, ‘run grunt with the ”watch” command’. If you look back at the grunt file, you’ll see that ‘watch’ is configured to look for that token, and send the signal to your browser.

Now that that’s started, on Chrome you’ll need to start the LiveReload extension watching for the signal. There’s ‘reload’ icon on the same line as the web address, with a little hollow circle surrounded by looping arrows. When you click it, the hollow circle is filled in, showing that the browser is connected to LiveReload. Be aware that it’s trying to connect to the LiveReload server you started with grunt watch, so you need to do it in that order — grunt, then browser.

We’re done! Now, whenever you build your web app, it will automatically refresh the browser. Although this was a bit of a slog, we’re now in the position where you don’t have to refresh your browser. If you have two monitors, you can code in one window and watch the web app develop in the other. Saves you mental energy and the RSI of constantly flicking your hand to the mouse!