Building a Self Updating Site Using NuGet

For those of you who enjoy learning about a technology via screencast, I’ve recorded a video to accompany and complement this blog post. The screencast shows you what this package does, and the blog post covers more of the implementation details.

A key feature of any package manager is the ability to let you know when there’s an update available for a package and let you easily install that update.

For example, when we deployed the release candidate for NuGet, the Visual Studio Extension Manager displayed the release in the Updates section.

Extension Manager Displaying NuGet as an Available Updates

Likewise, NuGet lets you easily see updates for installed packages. You can either run the List-Package –Updates command:

list-package-updates

Or you can click on the Updates node of the Add Package dialog:

updates-tab

This feature is very handy when using Visual Studio to develop software such as Subtext, an open source blog engine I run in my spare time. But I started thinking about the users of Subtext and the hoops they jump through to upgrade Subtext itself.

Wouldn’t it be nice if Subtext could notify users when a new version is available and let them install it directly from the admin section of the running website completely outside of Visual Studio? Why yes, that would be nice.

NuGet to the Rescue!

Well my friends, that’s where NuGet comes into play. While most people know NuGet as a Visual Studio extension for pulling in and referencing libraries in your project, there’s a core API that’s completely agnostic of the hosting environment whether it be Visual Studio, PowerShell, or other. That core API is implemented in the assemly, NuGet.Core.dll.

This assembly allows us to take advantage of many of the features of NuGet outside of Visual Studio such as within a running web site!

The basic concept is this:

  1. Package up the first version of a website as a NuGet package.
  2. Install this package in the website itself. I know, crazy talk, right?
  3. Add a custom NuGet client that runs inside the website and checks for updates to the one package that’s installed.
  4. When the next version of the website is ready, package it up and deploy it to the package feed for the website. Now, the users of the website can be notified that an update is available.s

I should point out a brief note about step #2, because this is going to be confusing. When I say install the package in the website, I mean to contrast that with installing a package into your Web Application Project for the website.

When you install a package into your Web Application Project, you use the standard NuGet client within Visual Studio. But when you deploy your website, the custom NuGet client within the live website will install the website package into a different location. In the example I’ll show you, that location is within the App_Data\packages folder.

The AutoUpdate Package

Earlier this week, I gave an online presentation to the Community For MVC (C4MVC) user’s group on NuGet. During that talk I demonstrated a prototype package I wrote called AutoUpdate. This package adds a new area to the target website named “Installation”. It also adds a nuspec file to the root of the application to make it easy to package up the website as a NuGet Package.

The steps to use the package are very easy.

  1. Install-Package AutoUpdate.
  2. In Web.config, modify the appSetting PackageSource to point to your package source. In my demo, I just pointed it to a folder on my machine for demonstration purposes. But this source is where you would publish updates for your package.
  3. In the Package Console, run the New-Package script (This creates packages up the website in a NuPkg file).
  4. Copy the package into the App_Data\Packages folder of the site.
  5. When you are ready to publish the next version as an update, increment the version number in the nuspec file and run the New-Package script again.
  6. Deploy the updated package to the package source.
  7. Now, when your users visit /installation/updates/check within the web site, they’ll be notified that an update is available and will be able to install the update.

The Results

Lets see the results of installing the AutoUpdate package and I’ll highlight some of the code that makes the package work. The following screenshot shows a very basic sample application I wrote.

home-page

The homepage here has a link to check for updates which links to an action within the area installed by the AutoUpdate package. That action contains the logic to check for updates for this application’s package.

Clicking on that link requires me to login first and then I get to this page:

update-available

As I mentioned in the steps before, I packaged up the first version of the application as a package and “installed” it into the App_Data folder.

That yellow bar above is the result of an asynchronous JSON request to see if an update is available. It’s a little redundant on this page, but I could have it show up on every page within the admin as a notification.

Under the Hood

Let’s take a look at the controller that responds to that asynchronous request.

public ActionResult Check(string packageId) {
  var projectManager = GetProjectManager();
  var installed = GetInstalledPackage(projectManager, packageId);
  var update = projectManager.GetUpdate(installed);

  var installationState = new InstallationState {
    Installed = installed,
    Update = update
  };

  if (Request.IsAjaxRequest()) {
    var result = new { 
      Version = (update != null ? update.Version.ToString() : null), 
      UpdateAvailable = (update != null)
    };
    return Json(result, JsonRequestBehavior.AllowGet);
  }

  return View(installationState);
}

The logic here is pretty straightforward. We grab a project manager. We then grab a reference to the current installed package representing this application. And then we check to see if there’s an update available. If there isn’t an update, the GetUpdate method returns false. There’s a couple of methods here that I wrote we need to look at.

The first method very simply retrieves a project manager. I encapsulated it into a method since I call it in a couple different places.

private WebProjectManager GetProjectManager() {
  string feedUrl = @"D:\dev\hg\AutoUpdateDemo\test-package-source";
  string siteRoot = Request.MapPath("~/");

  return new WebProjectManager(feedUrl, siteRoot);
}

There’s a couple things to note here. I hard coded the feedUrl for demonstration purposes to point to a directory on my machine. This is a nice demonstrations that NuGet can simply treat a directory containing packages as a package source.

For your auto-updating web application, that should point to a custom feed you host specifically for your website. Or, point it to the official NuGet feed and put your website up there. It’s up to you.

This method returns an instance of WebProjectManager. This is a class that I had to copy from the System.Web.WebPages.Administration.dll assembly because it’s marked internal. I don’t know why it’s internal, so I’ll see if we can fix that. It’s not my fault so please direct your hate mail elsewhere. Smile

What is the web project manager? Well the WebMatrix product which includes the ASP.NET Web Pages framework includes a web-based NuGet client for simple web sites. This allows packages to be installed into a running website. I’m just stealing that code and re-purposing it for my own needs.

Now, we just need to use the project manager to query the package source to see if there’s an update available. This is really easy.

private IPackage GetInstalledPackage(WebProjectManager projectManager, 
string packageId) { var installed = projectManager.GetInstalledPackages("AutoUpdate.Web")
.Where(p => p.Id == packageId); var installedPackages = installed.ToList(); return installedPackages.First(); }

What’s really cool is that we can just send a LINQ query to the server because we’re running OData on the server, it’ll run that query on the server and send us back the packages that fulfill the query.

That’s all the code necessary to check for updates. The next step is to write an action method to handle the upgrade. That’s pretty easy too.

public ActionResult Upgrade(string packageId) {
  var projectManager = GetProjectManager();
  var installed = GetInstalledPackage(projectManager, packageId);
  var update = projectManager.GetUpdate(installed);
  projectManager.UpdatePackage(update);

  if (Request.IsAjaxRequest()) {
    return Json(new { 
      Success = true, 
      Version = update.Version.ToString()
    }, JsonRequestBehavior.AllowGet);
  }
  return View(update);
}

This code starts off the same way that our code to check for the update does, but instead of simply returning the update, we call projectManager.UpdatePackage on the update. That method call updates the website to the latest version.

The rest of the method is simply concerned with returning the result of the upgrade.

Try it Yourself

If you would like to try it yourself, please keep a one big caveat in mind. This is rough proof of concept quality code. I hope to shape it into something more robust over time and publish it in the main package feed. Until then, I’ll post it here for people to try out. If there’s a lot of interest, I’ll post the source on CodePlex.com.

So with that in mind, give the AutoUpdate package a try

install-package AutoUpdate

and give me some feedback!

What others have said

Requesting Gravatar... Chris Jan 15, 2011 11:20 AM
# re: Building a Self Updating Site Using NuGet
Funny. I had this thought a while back. http://twitter.com/#/claco/status/20599774260502528

Will the install.ps1 files still be executed?
Requesting Gravatar... haacked Jan 15, 2011 11:30 AM
# re: Building a Self Updating Site Using NuGet
@Chris heh, so did I. Took me a while to get around to blogging around it.

No, the install.ps1 scripts will not run in this environment because it's running as part of your website, which doesn't have a PS environment like VS does.
Requesting Gravatar... NC Jan 15, 2011 12:15 PM
# re: Building a Self Updating Site Using NuGet
You've missed a closing tag on your post and it's screwed up all the comments in Firefox 4 beta and Opera 11.
Requesting Gravatar... NC Jan 15, 2011 12:24 PM
# re: Building a Self Updating Site Using NuGet
Where you have the title "Try it yourself" you have:

<h2 /> <--- screwing up browsers.

<h2>Try it Yourself</h2>
Requesting Gravatar... haacked Jan 15, 2011 12:51 PM
# re: Building a Self Updating Site Using NuGet
@NC Thanks! Fixed!
Requesting Gravatar... Mikael Henriksson Jan 15, 2011 3:16 PM
# re: Building a Self Updating Site Using NuGet
Phil, this is brilliant!! I was just a few weeks ago asking my hosting provider for a better alternative than ftp upload triggered from local machine.

Would this work in Medium++ trust? Either way I'd love to see the source code for this. The MvcScaffolding project that Sanderson just blogged about opened my eyes to NuGet, haven't really used it before.
Requesting Gravatar... Asad. Gharighi Jan 15, 2011 3:48 PM
# re: Building a Self Updating Site Using NuGet
It's quite useful to have such easy process. Thanks for sharing the idea and actually doing it.
I was thinking, if we had a way to do this autoupdates in a partial manner that would me more useful. You can see here and there some of the features of a new version maybe in conflict with someone's way of arranging things. Does that mean we should have a package manager inside the package manager? Maybe the original package should be maintaiend very carefully.
Thanks pal anyway.
Requesting Gravatar... Ben Foster Jan 15, 2011 5:23 PM
# re: Building a Self Updating Site Using NuGet
Phil, this looks great. It would good to extend this concept further to create a way of deploying and maintaining features/plugins within an application. There are so many OSS projects that would benefit from a standardised way of doing this.

Orchard already has something like this - are they using Nuget.Core too?
Requesting Gravatar... VDMT Jan 15, 2011 5:43 PM
# re: Building a Self Updating Site Using NuGet
Hi Phil, I like! This is awesome I'm looking forward to using this - not that you would normally do this but, would it be possible to extend this to revert back to a previous version?
Requesting Gravatar... Richard Kimber Jan 15, 2011 9:02 PM
# re: Building a Self Updating Site Using NuGet
This is fantastic. One of the features I've always loved about WordPress is autoupdate, now I can do it on my own apps.

Rich
Requesting Gravatar... Mike Jan 15, 2011 10:51 PM
# re: Building a Self Updating Site Using NuGet
How to handle permissions to update files, and how to handle database schema updates?
Requesting Gravatar... Corey Coto Jan 16, 2011 5:05 AM
# re: Building a Self Updating Site Using NuGet
Fantastic post!

How would this work in a IIS Web Server farm? Would it only update a single instance or all of the nodes in the farm?
Requesting Gravatar... haacked Jan 16, 2011 5:25 AM
# re: Building a Self Updating Site Using NuGet
@Mikael Medium trust should be no problem. It's really an issue of whether you allow write permissions to the web directory.

@Ben yes, look at what the ASP.NET Web Pages + Web Matrix does. They use this to add features/plugins via a web admin.

@VDMT in theory, yes you could revert. But I probably wouldn't trust it. ;)

@Mike Updating databases is tricky. What we do in Subtext is have an embedded resource with SQL scripts and we run the scripts when we do an update. You'd have to handle that in the code of your package somehow.

@Corey good point. It would only update a single instance. For a Web Farm, you'd have to have some way of syncing such changes across the farm.
Requesting Gravatar... Gregor Suttie Jan 16, 2011 6:32 AM
# re: Building a Self Updating Site Using NuGet
This is a superb addition!
Requesting Gravatar... Bob Jan 16, 2011 12:54 PM
# re: Building a Self Updating Site Using NuGet
Great post!! Videos always make it easier to learn. 720p video is a must for showing things on a computer screen. You've definitely elevated your level of blogging. It will be hard to do a "quickie" blog post in the future though. The expectations are now set too high!!
Requesting Gravatar... Robert Muehsig Jan 16, 2011 6:22 PM
# re: Building a Self Updating Site Using NuGet
Very impressive demo, but I´m a bit confused: I thought NuGet would be a kind of library repository. In your demo you use it for a whole web application - which is very cool. But should this "deployment task" not handled via WebDeploy? If I want to build a system like "Wordpress", should I upload new releases on MS WebApp Gallery for the Web Platform Installer AND on the NuGet Gallery?
SRP violation? ;)
Requesting Gravatar... Robert Jan 16, 2011 10:34 PM
# re: Building a Self Updating Site Using NuGet
Excellent post!

Please do make it available on Codeplex.
Requesting Gravatar... BobM Jan 17, 2011 2:11 AM
# re: Building a Self Updating Site Using NuGet
Interesting concept -- Pls make the code available. Can you think of any reason the same process could not be used to update windows services?
Requesting Gravatar... Martin Jan 17, 2011 10:14 AM
# re: Building a Self Updating Site Using NuGet
Could you please update the Mvc Futures on Nuget to the lateste version for MVC 3 RTM ? :)

Would be really great.
Requesting Gravatar... Andrew Wrigley Jan 17, 2011 5:27 PM
# re: Building a Self Updating Site Using NuGet
Registering interest
Requesting Gravatar... Ben Foster Jan 17, 2011 8:58 PM
# re: Building a Self Updating Site Using NuGet
"@Ben yes, look at what the ASP.NET Web Pages + Web Matrix does. They use this to add features/plugins via a web admin."

Phil,
Is this code (Web Matrix) open source?
Requesting Gravatar... Ira Jan 17, 2011 10:45 PM
# re: Building a Self Updating Site Using NuGet
This is quite an awesome idea. I for one really hope you release the source and make this a project on codeplex because I can think of a bunch of scenarios this would be useful in.
Requesting Gravatar... Jeff Jan 18, 2011 4:34 AM
# re: Building a Self Updating Site Using NuGet
This is pretty cool for personal blogs and sites where downtime is acceptable. However, inevitable a breaking change will be introduced by one of the dependencies and then "BOOM"!
Requesting Gravatar... Lee Hull Jan 18, 2011 1:30 PM
# re: Building a Self Updating Site Using NuGet
Very nice concept, unfortunately I'm getting an error..

"Could not load file or assembly 'NuGet.Core, Version=1.0.10128.89, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified."

However I do have NuGet.Core installed and referenced in website but not that exact version, I have NuGet.Core v1.0.11220.104
Requesting Gravatar... Hans Kruse Jan 19, 2011 3:47 AM
# re: Building a Self Updating Site Using NuGet
Can this be easily transformed into something useful for use from msbuild?

Now using nuget in VS.NET but a "sharedlibs" folder on the TFS buildserver due to lack of time.
Requesting Gravatar... haacked Jan 19, 2011 4:03 AM
# re: Building a Self Updating Site Using NuGet
@Robert I suppose it depends. Let's say you set up a blog for your mom. Do you expect her to use Web Deploy to deploy an updated version of that blog? I'm guessing no. It'd be nice if the blog could let her click a button in the website and upgrade itself.

Let's say you're at work and ready to deploy version 2 of your flagship website. Are you going to use this AutoUpdate NuGet package? Of course not. You'd use web deploy or something similar.

Every tool has its place.

@BobM I doubt this would work for Windows Services as a service needs to be stopped to be updated AFAIK. That's out of scope of NuGet.

@Ben WebMatrix is not open source. WebMatrix refers to the simple IDE we released.

@Jeff true. I probably wouldn't do enterprise deployments this way. But for web apps that are distributed, it's a neat idea.
Requesting Gravatar... Lee Hull Jan 19, 2011 11:49 AM
# re: Building a Self Updating Site Using NuGet
Got it working..

Really nice, would be nice if you could get update if local one does not exist. Since I publish to IIS, App_Data doesn't always get copied over
Requesting Gravatar... Oisin Grehan Jan 20, 2011 5:51 AM
# re: Building a Self Updating Site Using NuGet
It's Get-Package now Phil, not List-Package ;-)
Requesting Gravatar... Cyriel Jan 27, 2011 6:31 PM
# re: Building a Self Updating Site Using NuGet
Hi Phil,

Let me start by saying: nice idea!

Anyway,

I was wondering what would happen in a scenario where multiple users have permission to update the application, and all of them get notified and click the upgrade link in the notification. Will the second (or third or whatever) request be terminated if the first one is in progress?
Requesting Gravatar... haacked Jan 28, 2011 5:36 AM
# re: Building a Self Updating Site Using NuGet
@Cyriel that's not built into my proof-of-concept, but it's something that could easily be accomplished in the UI by setting some value in the database before starting the upgrade and always checking that value beforehand.
Requesting Gravatar... Joshua Feb 09, 2011 7:39 AM
# re: Building a Self Updating Site Using NuGet
This is an excellent idea Phil! I'd love to see this taken further.

Even for a simple blog website however, you still have a database to manage and I'm not sure how you would control database updates between versions? You would need a way of being able to pull down the appropriate sql migration script and run it on the database as part of a post build task or something.

Slight segway but I am also interested to see how the EF team handle code first migration.

I would love to see this proof of concept "AutoUpdater" project taken further. Just goes to show how awesome NuGet is.
Requesting Gravatar... Cody Feb 13, 2011 5:30 PM
# re: Building a Self Updating Site Using NuGet
I don't really see database updates being that challenging, they just require a bit of a workaround. Deploy the update script as part of your package and throw a little code into global.asax Application_Start to check a variable that records the last run version number. If the stored version number is older than the current version number, check if there's an update script and run it if so.

Certainly, it would be better to have this functionality baked into the update mechanism, which doesn't seem too hard or very involved. While it's probably not necessary, I have a feeling people might have more than a couple lines of SQL to run, so a little prescriptive design might encourage putting their update code into an assembly that is simply run as an automatic last stage of the updater.
Requesting Gravatar... haacked Feb 15, 2011 12:12 AM
# re: Building a Self Updating Site Using NuGet
@Cody, that's exactly how Subtext does it today and exactly how I'd probably do it with this package.
Requesting Gravatar... Patrick Feb 19, 2011 6:59 AM
# re: Building a Self Updating Site Using NuGet
This is exactly the type of thing I have been looking for. Any chance you can share the source?
Requesting Gravatar... Fabio Franzini Mar 22, 2011 1:27 AM
# re: Building a Self Updating Site Using NuGet
I created a demo project in web form at this address: www.fabiofranzini.com/...

Fabio
Requesting Gravatar... adrian Apr 15, 2011 9:57 AM
# re: Building a Self Updating Site Using NuGet
This is great! Luckily I did a google search before trying to implement it myself from scratch :) Codeplex is the right place for this one!
Requesting Gravatar... adrian Apr 15, 2011 6:51 PM
# re: Building a Self Updating Site Using NuGet
Please make the code available on Codeplex!

I got this error: [InvalidOperationException: The 'schemaVersion' attribute is not declared.]

Requesting Gravatar... Lasse Edsvik May 01, 2011 11:12 PM
# re: Building a Self Updating Site Using NuGet
Seems no controllers gets created when installing it to a mvc 3 site :) Could you fix that? :)
Requesting Gravatar... Attila Szomor May 05, 2011 5:26 PM
# re: Building a Self Updating Site Using NuGet
Hi Phil,

Your article was very useful for me and I am interesting for solutions such as AutoUpdate.
Please let me inform about what happened since you published this article.
Are you post (or will be) AutoUpdate into CodePlex?

Best Regards,
Attila.
Requesting Gravatar... Germán Jun 03, 2011 4:13 AM
# re: Building a Self Updating Site Using NuGet
Phil, great article.
By the way, i´m getting "Access denied" all the time because the selfupdater tries to delete a bin\.dll file used by the website, more specifically when trying to delete with "NuGet.PhysicalFileSystem.DeleteFile"
i`m getting a big "System.UnauthorizedAccessException: Access to the path 'D:\MySite\bin\MySite.dll' is denied."
How can you get through this ?
Requesting Gravatar... Nikos Miliotis Jun 18, 2011 4:52 AM
# re: Building a Self Updating Site Using NuGet
I have installed the package but no nuspec file is created either the views. (MVC 3) Am i missing something? I have watched the video but a lot of files are missing.
Requesting Gravatar... Mike Jul 16, 2011 6:04 AM
# re: Building a Self Updating Site Using NuGet
Awesome, but if this works, then what did we learn web deploy for?
Requesting Gravatar... Mike Jul 16, 2011 6:09 AM
# re: Building a Self Updating Site Using NuGet
"This method returns an instance of WebProjectManager. This is a class that I had to copy from the System.Web.WebPages.Administration.dll assembly because it’s marked internal. I don’t know why it’s internal, so I’ll see if we can fix that. It’s not my fault so please direct your hate mail elsewhere. "

Sure, but I'm not sure where Microsoft will direct the lawyers when I use AutoUpdate with code from copyrighted code...
Requesting Gravatar... David Jul 26, 2011 3:26 AM
# re: Building a Self Updating Site Using NuGet
Is there anything special you have to do with the package repository (D:\temp\packages)? I can't seem to get it to figure out that I have any updates even though I've put two nupkg files in there.
Requesting Gravatar... Paul Mendoza Jul 26, 2011 11:41 PM
# re: Building a Self Updating Site Using NuGet
Hi Phil,
Can you post this project to Codeplex? I'm really interested in using this.

Thanks,
Paul Mendoza
Requesting Gravatar... Husain Oct 13, 2011 4:28 PM
# re: Building a Self Updating Site Using NuGet
Phil, am interested in the code. Could you please post this on Codeplex? Thanks.
Requesting Gravatar... Peter Oct 15, 2011 9:14 PM
# re: Building a Self Updating Site Using NuGet
Hi Phil,
This is nifty stuff! Could you please post the code somewhere?
Many thanks for this post.
Requesting Gravatar... Davide Nov 11, 2011 9:53 AM
# re: Building a Self Updating Site Using NuGet
Any news about this?

Have you already published the source code? I've been looking for such a tool for a long time and only found half-baked overpriced commercial solutions.

Your way utilizing NuGet looks very promising. :)
Requesting Gravatar... Dmitriy Jan 03, 2012 5:10 PM
# re: Building a Self Updating Site Using NuGet
Looking forward to see the code as well; this sounds very cool!
Requesting Gravatar... Dmitriy Jan 03, 2012 5:19 PM
# re: Building a Self Updating Site Using NuGet
After more research, found it here: http://nuget.org/packages/AutoUpdate

Going to play around with this, thx.
Requesting Gravatar... Ryan Whitmire Jan 10, 2012 7:31 PM
# re: Building a Self Updating Site Using NuGet
Does this still work (as of nuget 1.6) or am I doing something wrong?
Requesting Gravatar... Yohann Jan 20, 2012 2:53 PM
# re: Building a Self Updating Site Using NuGet
I think the version 0.21 (the latest) doesn't work anymore... damn it!
Requesting Gravatar... click Jan 25, 2012 6:28 AM
# re: Building a Self Updating Site Using NuGet
Thank you for your help.I think i am getting it. I was able to send a link in the email that would take me to the Edit Properties page of the form, But i was expecting to get the actual form itself.
Requesting Gravatar... Avioes a Venda Feb 01, 2012 2:09 PM
# re: Building a Self Updating Site Using NuGet
I have watched the video but a lot of files are missing.
Requesting Gravatar... Aeronaves Feb 23, 2012 1:19 PM
# re: Building a Self Updating Site Using NuGet
Could you please post the code somewhere?
Many thanks for this post.
Requesting Gravatar... marko Apr 09, 2012 2:38 PM
# re: Building a Self Updating Site Using NuGet
Phil, please revisit this project of yours and publish it on some code sharing site (source code) so we can pick it up and maybe update it to work with the latest Nuget and maybe add functionality.

What do you have to say?

(will show your gravatar)
Please add 7 and 4 and type the answer here: