I wrote a post a few days ago called "Creating a NuGet Package in 7 easy steps - Plus using NuGet to integrate ASP.NET MVC 3 into existing Web Forms applications." Long enough title? I think so.
The post exists for two reasons: First to show folks how insanely easy it is to create a NuGet package (and prompt you to make some yourself) and second to share with you some experiments where one enables new/interesting functionality after File|New Project. In that example, we had an existing ASP.NET WebForms application and added ASP.NET MVC to it in one line, making it an easy hybrid application.
Well, not really one line. In version 0.5 of the AddMvc3ToWebForms package you still have to hook up the Areas, Routes and Filters yourself in the Global.asax. I made a helper method that gets it done to one additional line, but still, it's ever so slightly lame.
Now, to THIS post that exists for two reasons: First, to show you how to create an update to a package, and what the update process looks like for the consumer. Second, to show you how (and why) you should put a tiny bit more effort in your packages up front so that things "just work" for the user.
CREATING AN UPDATE TO A NUGET PACKAGE
Step 1 - Update the NuSpec file
I opened up my AddMvc3ToWebForms.nuspec file and changed the version a notch to 0.6. I also added a dependency to another NuGet package called WebActivator that I'm going to use to make my package just work and avoid the need for that extra line of code. I'm being specific and asking for WebActivator 1.1 or higher because that version has a specific feature I need.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<? xml version = "1.0" ?> < package xmlns:xsd = "http://www.w3.org/2001/XMLSchema" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" > < metadata xmlns = "http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd" > < id >AddMvc3ToWebForms</ id > < version >0.6</ version > < authors >Scott Hanselman</ authors > < owners >Scott Hanselman</ owners > < iconUrl >http://www.hanselman.com/images/nugeticon.png</ iconUrl > < requireLicenseAcceptance >false</ requireLicenseAcceptance > < description >A totally unsupported way to quickly add ASP.NET MVC 3 support to your WebForms Application. Works on my machine.</ description > < tags >MVC MVC3 ASP.NET WebForms</ tags > < dependencies > < dependency id = "WebActivator" version = "1.1" /> </ dependencies > </ metadata > </ package > |
Step 2 - Make your new changes
When bringing in multiple NuGet packages it's common to want to have a few things run at application startup. Perhaps setting some context, connection strings, defaults for software factories, or dependency resolvers. There are a number of packages that need this functionality, and David Ebbo created the WebActivator package to make it easier. It's a formalized wrapper around a new ASP.NET 4 attributed called "PreApplicationStartMethod," and David also enables a PostApplicationStartMethod.
In my new version of the AddMvc3ToWebForms package I created a new file called AppStart_RegisterRoutesAreasFilters.cs.pp. Note the .pp extension that signals to NuGet to preprocess the file and replace tokens like $rootnamespace$, kind of like a mini-mini-code-generator.
The rest should look familiar; we're registering the Areas, GlobalFilters and Routes. The informal naming convention is to prefix the class and file with AppStart_ so that projects that include packages that add an AppStart_*.* will group the files together.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; using Microsoft.Web.Infrastructure; [assembly: WebActivator.PostApplicationStartMethod( typeof ($rootnamespace$.AppStart_RegisterRoutesAreasFilters), "Start" )] namespace $rootnamespace$ { public static class AppStart_RegisterRoutesAreasFilters { public static void Start() { // Set everything up with you having to do any work. // I'm doing this because it means that // your app will just run. You might want to get rid of this // and integrate with your own Global.asax. // It's up to you. AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); } public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add( new HandleErrorAttribute()); } public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute( "{resource}.axd/{*pathInfo}" ); routes.MapRoute( "Default" , // Route name "{controller}/{action}/{id}" , // URL with parameters new { controller = "Home" , action = "Index" , id = UrlParameter.Optional } // Parameter defaults ); } } } |
Note the line:
[assembly: WebActivator.PostApplicationStartMethod(typeof($rootnamespace$.AppStart_RegisterRoutesAreasFilters), "Start")]
David added the "PostApplicationStart" option because PreApplicationStart happens too early in the process to register Areas, so for my package, I want things to run just after App_Start. This is all new and under development, so feel free to share with David if you have any thoughts, improvements or strong opinions.
Step 3 - Build a new NuPkg file
From the command line, call...
NuGet pack
...and you'll automatically get a new file, like this screenshot:
Step 4 - Publish the Update to http://nuget.org (or any NuGet server or file share)
I could log in to my account and upload the file from the browser interface, but since I'm thinking I'll being making changes here and there, I figure it'd be nice to publish from the command line.
I'll grab my API key from the site...
..and use it to publish from the command line (using my magic new publish.bat) with contents like these:
nuget push AddMvc3ToWebForms.0.6.nupkg e5c2bbe6-xxxx
...and the result...
C:AddMvc3ToWebForms>nuget push AddMvc3ToWebForms.0.6.nupkg e5c2bbe6-xxxx
Creating an entry for your package [ID:AddMvc3ToWebForms Ver:0.6]...
Your package was uploaded to the server but not published.
Publishing your package [ID:AddMvc3ToWebForms Ver:0.6] to the live feed...
Your package was published to the feed.
Now I'm set. I've got version 0.6 live now. What's the experience for the user of this library?
GETTING AN UPDATE TO A NUGET PACKAGE
There's two ways to find out what NuGet packages my project is using and update them.
Package Manager Console
From the package manager console I can type Get-Package...
PM> Get-Package
Id Version Description
-- ------- -----------
AddMvc3ToWebForms 0.5 A totally unsupported way to quickly add ASP.NET MVC 3 support to your WebForms Application. Works on my machine.
Looks like I have version 0.5. I can update it via...
PM> Update-Package AddMvc3ToWebForms
'WebActivator (≥ 1.1)' not installed. Attempting to retrieve dependency from source...
Done.
Successfully installed 'WebActivator 1.1.0.0'.
Successfully installed 'AddMvc3ToWebForms 0.6'.
Successfully removed 'AddMvc3ToWebForms 0.5' from WebApplication7.
Successfully uninstalled 'AddMvc3ToWebForms 0.5'.
Successfully added 'WebActivator 1.1.0.0' to WebApplication7.
Successfully added 'AddMvc3ToWebForms 0.6' to WebApplication7.
Notice that NuGet automatically removed AddMvc3ToWebForms 0.5 and installed AddMvc3ToWebForms 0.6. It also automatically brought in the dependency on WebActivator 1.1.
Add Library Reference
Alternatively, from Visual Studio right click on the References node in the Solution Explorer and select Add Library Reference (or select the same directly from the Tools menu).
Select Updates from the left side. A list of updates will appear. Click Update.
It's all good. Now my AddMvc3ToWebForms NuGet Package can add ASP.NET MVC functionality to an ASP.NET WebForms projects with no additional lines of code. This makes for a nice out of the box experience, especially if I bring in other projects that use the same functionality.