Friday, March 11, 2011

Saving your API key with nuget.exe

While you can push NuGet packages from http://nuget.org/, it is often more convenient to do it straight from the command line using nuget.exe.

Phil did a nice post on how that works, which you should read first if you have not done this before.

The one pain point about this technique is that you need to find your API key every time you push a package. I have had to go to http://nuget.org/Contribute/MyAccount each time to locate my key, copied it and pasted it on the command line. It gets old quickly! :)

The good news is that the newest version of nuget.exe (get it here) lets you save it once and for all! Credit goes to Matthew Osborn for this new feature.

Here is how it works.

Saving your key

First, you run the new SetAPIKey command, e.g.

D:\test>nuget SetApiKey 78a53314-c2c0-45c6-9d92-795b2096ae6c
The API Key '78a53314-c2c0-45c6-9d92-795b2096ae6c' was saved for the source 'http://go.microsoft.com/fwlink/?LinkID=207106'.

This encrypts the key and saves it in a config file under your %APPDATA% folder. e.g. mine ends up in C:\Users\davidebb\AppData\Roaming\NuGet\NuGet.Config. This file contains:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<apikeys>
  <add key="http://go.microsoft.com/fwlink/?LinkID=207106" value="AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAnMGkdu4+rkqpSdQUWwjfIgAAAAACAAAAAAADZgAAwAAAABAAAAA5gG4wxeb8Vn4X0Y0p//OvAAAAAASAAACgAAAAEAAAAF/llublBpBgL9lSFaE9/A0oAAAAC4NVHflYsUU5UgVgOq+h3t1jwY6l2BEji6Td4F0lvxsZcZ73L2m6BRQAAABJ0TZLKdIYStn8DWawbtzdo3mrKg==" />
</apikeys>
</configuration>

Note that the key is saved per server URL, with the server defaulting to nuget.org (you can pass -src to change that).

Using the saved key

Once you have done this one-time step, pushing packages becomes a breeze, as the only thing you need to pass is your package file. e.g.

D:\test>nuget push DavidTest.1.0.nupkg
Publishing DavidTest 1.0 to the live feed...
Your package was published to the feed.

Likewise, if you want to delete a package, you’d do:

D:\test>nuget delete -noprompt DavidTest 1.0
Deleting DavidTest 1.0 from the server.
DavidTest 1.0 was deleted from the server

Hopefully this will make your NuGet package management experience a little bit easier!

Thursday, March 10, 2011

Using NuGet without committing packages

 

Update (8/16/2011): also check out this newer post that describes an easier way to set up this workflow.

The current NuGet workflow has always been to commit the Packages folder into source control. The reasoning is that it matches what developers typically do when they don’t have NuGet: they create a ‘Lib’ or ‘ExternalDependencies’ folder, dump binaries into there and commit them to source control to allow others to build.

While this has worked fine for some users, we have also heard from many that committing packages into source control is not what they want to do. When using a DVCS like Mercurial or Git, committing binaries can grow the repository size like crazy over time, making cloning more and more painful. In fact, this has been one of the top requests on NuGet our issue tracker.

The good news is that NuGet now offers a workflow which goes a long way to solving this problem. It isn’t 100% automated yet, but with some minimal pain you can set up your project to do this.

Running ‘nuget install’ on a packages.config file

Earlier, I blogged about how you can install NuGet packages from the command line by using NuGet.exe.

Get NuGet.exe from here if you don’t already have it, and run ‘nuget -update’ to self-update it.

This lets you install one package at a time, e.g.

D:\Mvc3Application>nuget install NHibernate -o Packages

As an aside, the -o flag is new and lets you specify where the package is installed.

But the big new thing is that you can now run it on a packages.config file. packages.config is a file that NuGet creates at the root of every project that has packages installed. So if you install the ‘EFCodeFirst.Sample’ package in your app, you’ll find a packages.config next to the .csproj file, and it will contain:

<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="EFCodeFirst" version="0.8" />
<package id="EFCodeFirst.Sample" version="0.8" />
</packages>

So this holds all the information about what packages are needed for your project. Suppose you don’t commit your Packages folder (which lives under the solution folder), and another developer clones your repository. They can now run:

D:\Mvc3Application>nuget i Mvc3Application\packages.config -o Packages
Successfully installed 'EFCodeFirst 0.8'.
Successfully installed 'EFCodeFirst.Sample 0.8'.

And the Packages will be restored! The other nice thing is that this command is smart enough not to do any expensive work if they are already installed, e.g.

D:\Mvc3Application>nuget i Mvc3Application\packages.config -o Packages
All packages listed in packages.config are already installed.

This completes very quickly with no network requests.

Integrating package restore into msbuild

Integrating this into your build is a simple matter of adding a Pre-build event.

First, I would suggest committing nuget.exe into your solution, e.g. under a Tools folder. Once you do that, you can then add the following Pre-build event:

$(SolutionDir)Tools\nuget install $(ProjectDir)packages.config -o $(SolutionDir)Packages

Note how packages.config lives under the project folder while the Packages folder lives under the solution folder.

And that’s it, you’re done! Now each time you build, NuGet will first make sure that you have all the packages that you need, and will download anything that’s missing from the live feed.

If your solution has multiple projects that use NuGet, add the same Pre-Build event to each project.

As an alternative, you can use an msbuild custom build target to achieve the same thing. Check out Danny Tuppeny's post for details on that. This worked better for him when using App Harbor.

We want your feedback

This is new, so it’s possible that it doesn’t quite work perfectly in all cases. Please let us know how it works for you: bugs, feedback, suggestion. Thanks!

Tuesday, March 8, 2011

Take NuGet to the next level with sample packages

NuGet has drastically simplified the process of getting .NET libraries into your projects. What used to be an error prone and painful process has become as simple as adding an assembly reference.

While it has solved an important part of the developer workflow, it has the potential to also solve another key piece of the puzzle: helping user learn to use libraries.

I found these cool packages, but now what?

There are tons of cool packages available on NuGet today, and the number is growing daily. I’ve heard of a number of users who go down the list and install all kind of packages into their projects to try them out. But if you’re not familiar with a library, how do you get started with it?

As an example to illustrate the discussion, let’s take the nifty little Clay package written by the Orchard guys. Say you have installed it into your project and want to start using it. Here is what you might do:

  • The NuGet dialog gives you a link to the ‘project URL’. Typically, it’s a link to where the project is hosted on CodePlex/BitBucket/github, and indeed this one takes you to http://clay.codeplex.com/.
  • Once you’re there, you try clicking on the Documentation tab. Unfortunately, many projects don’t have much there. But here it at least has a pointer to Bertrand’s blog posts on the topic. So you now go to his post.
  • You read through it, and after a while, you can piece together enough bits and pieces to know what it’s about and start using it into your code.

I took Clay as an example, but this is a fairly typical experience. The fact is that a lot of knowledge about immature (yet useful) projects only exists in ‘blog post series’ rather than in any formal documentation. Not ideal, but that’s how things happen.

NuGet to the rescue with Sample Packages

Luckily, there is a simple and effective solution to this problem: use NuGet to distribute basic samples that get your users on the right path with less pain.

So to illustrate this post, I went ahead and created one such package for Clay: Clay.Sample. This package depends on Clay, such that installing it also installs Clay (as well as other things Clay depends on, like Castle).

It’s a ‘source only’ package, meaning that it doesn’t contain any binaries of its own. So let’s go ahead and try it in a brand new Console app (and change it NOT to use the client profile). Go in NuGet’s ‘Add Library Reference’ dialog and search for Clay. You’ll get this:

image

After you install it, your project will look like this:

image

First, note how you got all the expected references to Clay and to its dependencies: Castle.* and log4net.

But more interestingly, it also brought in a ClaySamples source file under Samples\Clay. It contains a number of Clay samples, which I shamelessly copied from Bertrand’s post. Here is one example:

public static void AnonymousObject() {
   dynamic New = new ClayFactory();

   var person = New.Person(new {
       FirstName = "Louis",
       LastName = "Dejardin"
   });

   Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
}
There are about 10 such samples in there, which demonstrate everything that the post discusses. Now go to your Console Main and make a call to a method that runs all the samples:
class Program {
   static void Main(string[] args) {
       Samples.Clay.ClaySamples.RunAll();
   }
}

While there is nothing in there that’s not in the blog post, the big advantage is that you can trivially get it into your project via NuGet, and you can then directly run/debug the samples without having to piece them together.

Of course, the blog post (or documentation) may still be worth reading for extra insight. But you may find that the samples give you all you need for now, and save the deeper reading for later.

Call to packages authors: write Sample packages!

I think this type of packages can have a huge impact on developer productivity. But for that to actually happen, those packages need to be created! And while I created the one for Clay, I am not volunteering to create all the sample packages :) Clearly, the best person to do that is the author of the package, though anyone who knows it well enough can certainly do it as well.

So if you own a NuGet package, please try to take on that task. It’s super easy, and your users will thank you for it!

Conventions, conventions, conventions

I recently blogged about using the App_Start convention for WebActivator startup code and got a great response, with almost all WebActivator users converting their existing packages to use this.

The situation here is quite similar, and calls for a similar convention, which is what I showed above. In a nutshell:

  • If your package is named Blah, call the sample package Blah.Sample. If you want multiple sample packages, you can call them Blah.Sample.Something and Blah.Sample.SomethingElse.
  • Make your Blah.Sample package dependent on Blah.
  • Within that package, just include source files. Place those file under the Samples\Blah. You can have one or more, and call them whatever you think make sense.
  • The code on there is up to you, but the general idea to to include whatever you think will help the user get started. Try to make the sample code easily runnable without too much extra setup. This may be harder for some packages, but do your best :)

Creating the package

Taking Clay as an example, here is the structure of the files before packing them into a nupkg:

├  Clay.Sample.nuspec
└──Content
└──Samples
 └──Clay
    └  ClaySamples.cs.pp

So there are just two files, the nuspec and the preprocessed sample file. Here is the nuspec:

<?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>Clay.Sample</id>
<version>1.0</version>
<authors>Outercurve Foundation</authors>
<owners>Outercurve Foundation</owners>
<licenseUrl>http://www.opensource.org/licenses/ms-pl</licenseUrl>
<projectUrl>http://clay.codeplex.com</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>This package contains samples that demonstrate the use of the Clay library.</description>
<language>en-US</language>
<dependencies>
<dependency id="Clay" version="1.0" />
</dependencies>
</metadata>
</package>

The interesting parts here are the package Id, the description, and the dependency on Clay.

Then ClaySamples.cs.pp is a normal source file, except for a tiny bit of preprocessing for the namespace, e.g.

using System;
using ClaySharp;

namespace $rootnamespace$.Samples.Clay {
   public static class ClaySamples {
      // Sample code here
   }
}

And that’s it! Once you have that, just run ‘nuget pack’ from the folder with the nuspec, and you’ll have a sample package ready to be pushed to the feed.

Sunday, March 6, 2011

Using a custom build of MVC 3

Disclaimer: running a custom build of MVC 3 is not recommended in most scenarios. Please run against the official MVC 3 bits unless you really cannot. Be aware that using custom builds will make it harder to use 3rd party libraries built against the official bits (you’ll need to rebuild those libraries).

One nice thing about ASP.NET MVC is that you can get the full sources on CodePlex and compile them yourself.

Once you copy the sources locally, you can open the WebRuntime solution in VS 2010 and build it. As an aside, note that this solution also contains the ASP.NET WebPages sources, since MVC3 makes you of some of that logic (mostly for Razor support).

So this lets you modify the sources and build everything. However, one thing that makes the use of the resulting assemblies a bit tricky is that unlike the official bits, the bits produced by this solution are unsigned.

Let’s take this step by step.

Step 1: Create a new MVC 3 application

So let’s start by creating a new MVC 3 Web Application using the regular project template that come from installing MVC 3.

This gives you a working app, but obviously at this point you're still using the official MVC 3 bits.

Step 2: Reference your custom assemblies

The next step is to reference your custom MVC assemblies. Start by removing the System.Web.Mvc and System.Web.WebPages references. Instead, reference the version you’ve built of those same assemblies, which you’ll find under mvc3\bin\Debug (from the root of the WebRuntime solution).

Once you do that, your MVC project will build fine. However, if you try running it, you’ll get some scary looking runtime compilation error. Something like:

CS0433: The type 'System.Web.Mvc.WebViewPage<TModel>' exists in both 'c:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Web.Mvc\v4.0_3.0.0.0__31bf3856ad364e35\System.Web.Mvc.dll' and 'c:\Users\David\AppData\Local\Temp\Temporary ASP.NET Files\root\d305385c\948d4291\assembly\dl3\ef116fd6\5f110ce1_44dccb01\System.Web.Mvc.DLL'

The reason this happens is that while you’ve changed the project references to point to your assembly, the two web.config files that come with the project template are still pointing to the official assemblies left and right. Which leads us to…

Step 3: Fix up your web.config files

The project comes with two web.config files, and they each contain all kind of references to the official assemblies (which are strong name). e.g. in the root web.config, you’ll find:

<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
Luckily, the fix is as simple as yanking the strong name from a few assemblies. This is easily done using a project-wide search/replace. Specifically, do the following three replacements:

1. Replace all instances of (excluding the quotes!)

“System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35”

by

“System.Web.Mvc”

2. Replace all instances of

“System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35”

by

“System.Web.WebPages”

3. Replace all instances of

“System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35”

by

“System.Web.WebPages.Razor”

And that should be it. Your app will now be up and running against your custom MVC bits.