DaedTech

Stories about Software

By

How To Put Your Favorite Source Code Goodies on Nuget

A while back, I made a post encouraging people to get fed up every now and then and figure out a better way of doing something. Well, tonight I take my own advice. I am sick and tired of rifling through old projects to find code that I copy and paste into literally every non-trivial .NET solution that I create. There’s a thing for this, and it’s called Nuget. I use it all the time to consume other people’s code, libraries and utilities, but not my own. Nope, for my own, I copy and paste stuff from other projects. Not anymore. This ends now.

My mission tonight is to take a simple bit of code that I add to all my unit test projects and to make it publicly available view Nuget. Below is the code. Pretty straightforward and unremarkable. For about 5 versions of MSTest, I’ve hated the “ExpectedException” attribute for testing that something throws an exception. It’s imprecise. All it tests is that somewhere, anywhere, in the course of execution, an exception of the type in question is thrown. Could be on the first line of the method, could be on the last, could happen in the middle from something nested 8 calls deep in the call stack. Who knows? Well, I want to know and be precise, so here’s what I do instead:

public static class ExtendedAssert
{
    /// Check that a statement throws a specific type of exception
    /// Exception type inheriting from Exception
    /// Action that should throw the exception
    public static void Throws(Action executable) where TException : Exception
    {
        try
        {
            executable();
        }
        catch (Exception ex)
        {
            Assert.IsTrue(ex.GetType() == typeof(TException), String.Format("Expected exception of type {0} but got {1}", typeof(TException), ex.GetType()));
            return;
        }
        Assert.Fail(String.Format("Expected exception of type {0}, but no exception was thrown.", typeof(TException)));
    }

    /// Check that a statement throws some kind of exception
    /// Action that should throw the exception
    /// Optionally specify a message
    public static void Throws(Action executable, string message = null)
    {
        try
        {
            executable();
        }
        catch
        {
            Assert.IsTrue(true);
            return;
        }
        Assert.Fail(message ?? "Expected an exception but none was thrown.");
    }

    /// Check that a statement does not throw an exception
    /// Action to execute
    public static void DoesNotThrow(Action executable)
    {
        try
        {
            executable();
        }
        catch (Exception ex)
        {
            Assert.Fail(String.Format("Expected no exception, but exception of type {0} was thrown.", ex.GetType()));
        }
    }

Now, let’s put this on Nuget somehow. I found my way to this link, with instructions. Having no idea what I’m doing (though I did play with this once, maybe a year and a half ago), I’m going with the GUI option even though there’s also a command line option. So, I downloaded the installer and installed the Nuget package explorer.

From there, I followed the link’s instructions, more or less. I edited the package meta data to include version info, ID, author info, and a description. Then, I started to play around with the “Framework Assemblies” section, but abandoned that after a moment. Instead, I went up to Content->Add->Existing file and added ExtendedAssert. Once I saw the source code pop up, I was pretty content (sorry about the little Grindstone timer in the screenshot — didn’t notice ’til it was too late):

PackageExplorer

Next up, I ran Tools->Analyze Package. No issues found. Not too shabby for someone with no idea what he’s doing! Now, to go for the gusto — let’s publish this sucker. File->Publish and, drumroll please…. ruh roh. I need something called a “Publish Key” to publish it to nuget.org.

PublishKey

But, as it turns out, getting an API key is simple. Just sign up at nuget.org and you get one. I used my Microsoft account to sign up. I uploaded my DaedTech logo for the profile picture and tweaked a few settings and got my very own API key (found by clicking on my account name under the “search packages” text box at the top). There was even a little clipboard logo next to it for handy copying, and I copied it into the window shown above, and, viola! After about 20 seconds, the publish was successful. I’d show you a screenshot, but I’m not sure if I’m supposed to keep the API key a secret. Better safe than sorry. Actually, belay that last thought — you are supposed to keep it a secret. If you click on “More Info” under your API key, it says, and I quote:

Your API key provides you with a token that identifies you to the gallery. Keep this a secret. You can always regenerate your key at any time (invalidating previous keys) if your token is accidentally revealed.

Emphasis mine — turns out my instinct was right. And, sorry for the freewheeling nature of this post, but I’m literally figuring this stuff out as I type, and I thought it might make for an interesting read to see how someone else pokes around at this kind of experimenting.

Okay, now to see if I can actually get that thing. I’m going to create a brand new test project in Visual Studio and see if I can install my beloved ExtendedAssert through Nuget, now.

NugetSuccess

Holy crap, awesome! I’m famous! (Actually, that was so easy that I kind of feel guilty — I thought it’d be some kind of battle, like publishing a phone app or something). But, the moment of truth was a little less exciting. I installed the package, and it really didn’t do anything. My source code file didn’t appear. Hmmm…

After a bit of googling, I found this stack overflow question. Let’s give that a try, optimistically upvoting the question and accepted answer before I forget. I right clicked in the “package contents” window, added a content folder, and then dragged ExtendedAssert into that folder. In order to re-publish, I had to rev the version number, so I revved the patch decimal, since this is a hot patch to cover an embarrassing release if I’ve ever seen one. No time for testing on my machine or a staging environment — let’s slam this baby right into production!

Woohoo! It worked and compiled! Check it out:

NugetInstallSuccess

But, there’s still one sort of embarrassing problem — V1.0.1 has the namespace from whichever project I picked rather than the default namespace for the assembly. That’s kind of awkward. Let’s go back to google and see about tidying that up. First hit was promising. I’m going to try replacing the namespace with a “source code transformation” as shown here:

s

Then, according to the link, I also need to change the filename to ExtendedAssert.cs.pp (this took me another publish to figure out that I won’t bore you with). Let’s rev again and go into production. Jackpot! Don’t believe me? Go grab it yourself.

The Lessons Here

A few things I’ll note at this point. First off, I recall that it’s possible to save these packages locally and for me to try them before I push to Nuget. I should definitely have done that, so there’s a meta-lesson here in that I fell into the classic newbie trap of thinking “oh, this is simple and it’ll just work, so I’ll push it to the server.” I’m three patches in and it’s finally working. Glad I don’t have tens of thousands of users for this thing.

But the biggest thing to take away from this is that Nuget is really easy. I had no idea what I was doing and within an hour I had a package up. For the last 5 years or so, every time I start a new project, I’d shuffle around on the machine to find another ExtendedAssert.cs that I could copy into the new project. If it’s a new machine, I’d email it to myself. A new job? Have a coworker at the old one email it to me. Sheesh, barbaric. And I put up with it for years, but not anymore. Given how simple this is, I’m going to start making little Nuget packages for all my miscellaneous source code goodies that I transport with me from project to project. I encourage you to do the same.

By

Nuget: Stop Copying and Pasting your Utils.cs Class Everywhere

I was setting up to give a presentation the other day when it occurred to me that Nuget was the perfect tool for my needs. For a bit of background, I consider it of the utmost importance to tell a story while you present. Things I’m not fond of in presentations include lots of slides without any demonstration and snapshots of code bases in various stages of done. I prefer a presentation where you start with nothing (or with whatever your audience has) and you get to some endpoint, by hook or by crook. And Nuget is an excellent candidate for whichever of “hook” and “crook” means “cheating.” You can get to where you’re going by altering your solution on the fly as you go, but without all of the umming and hawing of “okay, now I’ll right click and add an assembly reference and, oh, darnit, what was that fully qualified path again, I think–oops, no not that.”

In general, I’ve decided to set up an internal Nuget feed for some easier ala carte development, so this all dovetails pretty nicely. It made me stop and think that, given how versatile and helpful a tool this is, I should probably document it for anyone just getting started. I’m going to take you through creating the simplest imaginable Nuget package but with the caveat that this adds a file to your solution (as opposed to other tutorials you’ll see that often involve marshaling massive amounts of assembly references or something). So, here are the steps (on Windows 7 with VS2012):

  1. Go to codeplex and download the package explorer tool.
  2. Install the package explorer, launch it, and choose “Create a New Package”:

    NugetCreateNew

  3. In the top left, click the “Edit Metadata” icon as shown here:

    EditMetadata

  4. Fill out the metadata, ensuring that you fill things in for the bold (required) fields:

    ActualMetadata

  5. Click the green check mark to exit the metadata screen and then right-click in the “Package Contents” pane. Select “Add Content Folder.” The “Content” folder is a structure of files that will mimic what Nuget puts in your solution.

    NewContent

  6. Now, right click on the “Content” folder and select “Add New File.” Name the file “Readme.txt” and add a line of text to it saying “Hello.” Click the save icon and then the “back” arrow next to it.
  7. Now go to the file menu at the top and select “Save,” which will prompt you for a file location. Choose the desktop and keep the default naming of the file with the “nupkg” extension. Close the package explorer.
  8. Create a new solution in Visual Studio into which we’re going to import the Nuget package.
  9. Go to Tools->Library Package Manager->Manage Packages for Solution to launch the Nuget GUI and click “Settings” in the bottom right because we’re going to add the desktop as a Nuget feed:

    NugetGui

  10. In this screen, click the plus icon (pointed to by the arrow) and then give the package a name and enter the file path for the desktop by way of configuration:

    AddPackageSource

  11. Click “Ok” and you should see your new Nuget feed listed underneath the official package source. If you click it, you should see your test package there:

    TestPackage

  12. Click “Install” and check out what happens:

    NugetSuccess

Observe that source (or text or whatever) files are installed to your solution as if they were MSI installs. You can install them, uninstall them, and update them all using a GUI. Source code is thus turned into a deliverable that you can consume without manual propagation of the file or some kind of project or library include of some “CommonUtils” assembly somewhere. This is a very elegant solution.

It shouldn’t take a ton of extrapolation to see how full of win this is in general, especially if you create a lot of new projects such as a consulting shop or some kind of generalized support department. Rather than a tribal-knowledge mess, you can create an internal Nuget feed and setup a sort of code bazaar where people publish things they think are useful; tag them with helpful descriptors; and document them, allowing coworkers to consume the packages. People are responsible for maintaining and helping with packages that they’ve written. Have two people do the same thing? No worries–let the free market sort it out in terms of which version is more popular. While that may initially seem like a waste, the group is leveraging competition to improve design (which I consider to be an intriguing subject, unlike the commonly embraced anti-pattern, “design by committee,” in which people leverage cooperation to worsen design).

But even absent any broader concerns, why not create a little Nuget feed for yourself, stored in your Dropbox or on your laptop or whatever? At the very least, it’s a handy way to make note of potentially useful things you’ve written, polish them a little, and save them for later. Then, when you need them, they’re a click away instead of a much more imposing “oh, gosh, what was that one thing I did that one time where I had a class kinda-sorta like this one…” away.