Extending Blaze with NuGet Support

TL;DR Version

I recently extended the open-source Blaze C# Script IDE with NuGet support. You can get the latest version at the Blaze project site, or check out the source code changes at Bitbucket.

Continuing on…

I am a big fan of REPL loops. Even if you’re not familiar with the term, you’ve probably used one as a software developer. Standing for “Read-Evaluate-Print Loop”, it’s a console-like entry where you can type code and immediately execute it and see the result. For an example, hit F12 on any page in Google Chrome and go over to the Console tab. You can start typing JavaScript and hit enter and it will immediately run.
As a C# developer, occasionally I find myself needing to use a REPL to validate logic. Of course, I could open up a new Visual Studio console application project and do it that way, but that takes a while to get set up and then you have to write a bunch of nasty other code to handle the console, and then you have all these files on your hard drive that you probably won’t use again. A REPL makes that situation so much easier, as you can just fire it up, type in your code, run it, and see the result without creating a single file on your hard disk (temporary files aside, of course).
Thanks to the Roslyn project, there will be a Microsoft-supported C# REPL sometime in the future. Until then, though, I’ve previously been using the good-but-not-great gsharp utility that’s included as part of the Mono project install. That is, until I heard about Blaze.
image
Blaze is a C# script IDE that is the next best thing to a C# REPL. In many ways, it’s better than a REPL, as it is document based, so you can save and load scripts to/from your hard drive, and you can run just a portion of the script by selecting the text to run and hitting F5. It’s developed by my colleague, fellow feature[23] lead software engineer Zachary Gramana.
Since I heard about Blaze shortly after starting with feature[23], I’ve been using it often for testing code and validating logic. It’s exactly what I need as a C# developer, and it’s now an essential part of my toolkit. You can download the app from the Codeplex project site by hitting the big Download button on the right side. It’s a ClickOnce application, so any time it gets updated you’ll get the latest version on launch.
One handy feature of Blaze is that you can add references to DLLs, via the “Reference Assemblies…” menu option under “Runtime Settings”. This allows you to add in, say, a reference to Json.NET (also known as Newtonsoft.Json) and test out JSON serialization using a third-party utility before adding it to your app.
That’s exactly what I was trying to do last week when I realized “hey wait a second, I usually add Json.NET to my project via NuGet, so now I have to hunt around for the DLLs!” After a bit of thinking and discussion, I realized that I could probably add NuGet support to Blaze! And so I did.
image

From the Add References screen, click Add a NuGet Package and you’ll get this dialog above. It’s designed like the Package Manager console, so you can type in the name just like you might see on the NuGet Gallery package page, like this one for Json.NET. (Specific versions with the --version argument are not yet supported.)
After typing in the term, hit enter, and it’ll search NuGet for the package. If it’s found, you’ll see any dependencies the package has, as well as it’s DLLs.
image
Selecting a DLL then clicking Add Selected References adds the reference to the parent dialog. If there are any dependencies, double-clicking on the dependency will jump to that NuGet package.
After adding the references, you can then use the DLLs as you normally would.
image

Using the NuGet API

The NuGet API is very clean and easy to use, but there aren’t many good tutorials out there for using it. Here’s a simple example tutorial, hopefully from here you can explore the rest of the API and make more advanced use of it. First, add a reference to NuGet.Core using NuGet (how meta is that?!). Next, create a new PackageRepository using the PackageRepositoryFactory:
var repo = PackageRepositoryFactory.Default.CreateRepository("https://nuget.org/api/v2/");
Of course, you eventually will want to not hard-code that link (although it’s currently hard-coded in Blaze). Next, if you’re looking for a package by its identifier (like we are in Blaze), you’ll call FindPackage on that repository, passing in the identifier as the sole parameter. (If you’d rather search, you can call repo.Search and handle the results differently.)
var result = repo.FindPackage("Newtonsoft.Json") as DataServicePackage;
This method can throw exceptions, like if there’s a 500 server error, so make sure this is wrapped in a try/catch. If it is successful, result will be a DataServicePackage instance. You’ll want to cast it as DataServicePackage so you have access to the package DownloadUrl property. To download the package, first new up a PackageDownloader.
var downloader = new PackageDownloader();
Now you can call DownloadPackage to do an HTTP request to download the package, which is basically a ZIP package.
var downloaded = downloader.DownloadPackage(new HttpClient(result.DownloadUrl), result) as NuGet.ZipPackage;
The DownloadPackage method is a blocking call that can also throw exceptions. Now that you have the ZipPackage, you’ll want to open it to extract the files. In our case, we’re looking for an exact file name to extract. In order to extract files, you must use the System.IO.Packaging namespace that’s in WindowsBase.dll, part of the .NET Framework 4.0. You’ll usually need to add a reference to this DLL, unless you’re writing a WPF app.
Finally, you’ll need to open the package stream, open the stream of the file within the package you want to extract, then copy the stream.
using (var stream = downloaded.GetStream())
{
    var zip = Package.Open(stream);

    var part = zip.GetPart(new Uri("/lib/net40/Newtonsoft.Json.dll", UriKind.Relative));
   
    string filePath = "C:\\Users\\Paul Irwin\\Desktop\\Newtonsoft.Json.dll";
   
    using (var zipFileStream = part.GetStream())
    using (var fileStream = new FileStream(filePath, FileMode.CreateNew))
    {
        zipFileStream.CopyTo(fileStream);
    }   
}
The namespaces you’ll want to include are NuGet, System.IO, and System.IO.Packaging. And, of course, I hard coded a number of strings in that example, but you should be able to take this from here and modify it as you please.
All in all I’ve enjoyed playing around with the NuGet API, and it was a fun project to work on!
Previous
Next Post »