Making Basic Requests Against the SlideShare API Using HammockREST
The project I'm currently working on involves numerous REST APIs from a multitude of very different services. In my initial prototype, which I've since scrapped, I went with trying to use a local wrapper for each REST API incorporated into my project, meaning I used the GData library for handling YouTube, FlickrNET for Flickr, etc...
As you can imagine, having N libraries for N different REST APIs in my service snowballed into a maintainability nightmare. In my new redesign I decided to use a generic REST wrapper in .NET, and as it so happens there are two full API-agnostic REST libraries in .NET: HammockREST and RestSharp. If there's one thing you can fault both of these libraries for, it's lack of documentation - they're both new comers to the .NET open source community, so I'm going to contribute some documentation for Hammock and RestSharp, starting with the SlideShare API for Hammock.
If you take a look at HammockREST's documentation, you can see how to structure a generic REST request for the Twitter API. Below is my full function for calling the get_slideshows_by_user from the SlideShare API using HammockREST; we'll start from the code and work backwards to explain what's going on underneath the hood.
public static string Query(string username) { RestClient client = new RestClient { Authority = "http://www.slideshare.net/api/", VersionPath = "2" }; client.AddHeader("User-Agent", "Hammock"); RestRequest request = new RestRequest { Path = "get_slideshows_by_user" }; string timestamp = QueryHelper.GetCurrentTimestamp(); request.AddParameter("api_key", Constants.SlideShareAPIKey); request.AddParameter("ts", timestamp); request.AddParameter("hash", QueryHelper.CalculateSHA1(Constants.SlideShareSharedSecret + timestamp, Encoding.UTF8)); request.AddParameter("username_for", username); RestResponse response = client.Request(request); return response.Content; }
Bear in mind that this is just meant to be simple example code to illustrate how HammockREST works with the SlideShareAPI, not something you'd stick in a production environment.
If you're unfamiliar with the SlideShare API remember that every request, even unauthenticated ones, requires the following three parameters:
- "api_key" - your SlideShareAPI developer key;
- "ts" - a UNIX-style timestamp; and
- "hash" - a hash of your SlideShareAPI developer shared secret plus the UNIX-style timestamp using SHA1. The hash must be in the order of secret + timestamp.
Given that I'm lazy, I borrowed the timestamp and SHA1 function Frederik Vig's original SlideShareNET wrapper. I'll post the source for both of those at the bottom of this post.
With that out of the way, let's look at the different HammockREST components in this code snippet and understand how they work:
RestClient client = new RestClient { Authority = "http://www.slideshare.net/api/", VersionPath = "2" };
This code defines a new Hammock.RestClient object, which specifies the general target for all subsequent API requests. Recall that the base URI for making requests against the SlideShare API is, as of writing this, http://www.slideshare.net/api/2/. In this source code I've expressed that as a combination of two properties:
- "Authority" - which is set to the root URI for all requests (http://www.slideshare.net/api/.)
- "VersionPath" - which in this case is version #2.
Whenever I execute a Hammock.RestRequest object using this Hammock.RestClient instance, all of those Requests will be executed against this URI: http://www.slideshare.net/api/2/. I could have just as easily accomplished this with the following code:
RestClient client = new RestClient { Authority = "http://www.slideshare.net/api/2/" };
The point is that the VersionPath property is optional - you can just specify the full base URL in the Authority property if you'd prefer to do it that way.
Let's take a look at the Hammock.RestClient instance:
RestRequest request = new RestRequest { Path = "get_slideshows_by_user" };
The way Hammock (and RestSharp, as you'll see) construct the URLs for REST requests is the following formula:
Request URL = {authority[/versionpath]}/{path}
Each individual RestRequest object is meant to map to a specific REST method call, so in this instance I'm trying to call the get_slideshows_by_user method from the SlideShare API. The code I've shown you thus far accomplishes that effectively, and in sticking with this API/method metaphor, we need to supply our REST API method with some arguments:
request.AddParameter("api_key", Constants.SlideShareAPIKey); request.AddParameter("ts", timestamp); request.AddParameter("hash", QueryHelper.CalculateSHA1(Constants.SlideShareSharedSecret + timestamp, Encoding.UTF8)); request.AddParameter("username_for", username);
This code is straight-forward enough - I add my three required parameters for any SlideShare request, and then I added parameter required specifically for get_slideshows_by_user, username_for, which specifies the SlideShare user whose presentations we want to retrieve via this API call.
Finally, we use the client to actually complete the REST API request:
RestResponse response = client.Request(request);
This returns a Hammock.RestResponse object, which is a container that includes data about the status of the request (i.e. if you ran into a HTTP error, other errors, etc...) and the API's response in string format.
That's the long and the short of it - in subsequent examples I'll show you how to automatically deserialize XML content into business objects using HammockREST and I'll show you how to do all of this using RestSharp too.
As promised, here's the functions (originally developed by Frederik Vig) which I used for generating the timestamps and hashes:
public static string GetCurrentTimestamp() { return Convert.ToInt32(Math.Floor((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds)).ToString(); }
using System.Security.Cryptography; public static string CalculateSHA1(string text, Encoding enc) { byte[] buffer = enc.GetBytes(text); var cryptoTransformSHA1 = new SHA1CryptoServiceProvider(); return BitConverter.ToString(cryptoTransformSHA1.ComputeHash(buffer)).Replace("-", "").ToLower(); }