I’m a little late to the party, but ComicVine have released an API for their online database of comics, characters, publishers, creators etc. It’s a fairly comprehensive REST API that lets you pull down details for just about anything in XML format. For example, to search for any character with “silver” in their name, you’d visit a URL like this (with your own API key):

http://api.comicvine.com/search/?api_key=…&resources=character&query=silver

I definitely want to build this into my next version of Comicster, and I want to do so in such a way that the user will be able to choose which online database they pull their information from (or upload to, if the database they select supports it).

My first thought when I saw the way this worked was that I’d need to use System.Net.WebClient to pull down the results, and then parse the XML somehow. Then I remembered a blog post from NathanA that I’d bookmarked on del.icio.us a while ago: WCF Web Programming or: How I Learned to Stop Worrying and Love Uri Templates. This post outlines a very cool way to access REST APIs using WCF, with the Flickr API as an example.

So here’s how I’ve started my ComicVine WCF client. First, an interface that gives me access to some of the more common search functions:

[ServiceContract]
internal interface IComicVineApi
{
    [WebGet(UriTemplate = "search/?api_key={key}&resources=character&query={query}&field_list=id,name,aliases,deck,image")]
    [OperationContract]
    XElement FindCharacters(string key, string query);

    [WebGet(UriTemplate = "search/?api_key={key}&resources=person&query={query}&field_list=id,name,aliases,deck,image,site_detail_url")]
    [OperationContract]
    XElement FindCreators(string key, string query);

    [WebGet(UriTemplate = "search/?api_key={key}&resources=publisher&query={query}&field_list=id,name,deck,site_detail_url")]
    [OperationContract]
    XElement FindPublishers(string key, string query);

    [WebGet(UriTemplate = "search/?api_key={key}&resources=volume&query={query}&field_list=id,name,description,image,start_year")]
    [OperationContract]
    XElement FindTitles(string key, string query);
}

As you can see, we simply map the parameters of each method to parameters in the corresponding URL. Each method returns an XElement which I can easily parse using Linq to XML.

To use this interface we spin it up using WCF, like this:

IComicVineApi _channel = new WebChannelFactory<IComicVineApi>(
    new Uri("http://api.comicvine.com")).CreateChannel();

Pretty neat, huh? We just pass the base URL into a WebChannelFactory and call the CreateChannel method to get an implementation of the interface!

All that’s left, then, is to provide a way to search for characters and return them as proper Comicster.Character objects:

public IEnumerable<Character> FindCharacters(string query)
{
    return from x in _channel.FindCharacters(key, query).Elements("results").Elements("character")
           let icon = (string)x.Element("image").Element("icon_url")
           select new Character
           {
               Name = (string)x.Element("name"),
               Details = (string)x.Element("deck"),
               OnlineId = (string)x.Element("id"),
               Aliases = (string)x.Element("aliases"),
               Image = icon == null ? null : new Uri(icon),
           };
}

As you see, it’s a simple Linq to XML query that walks over the returned XElement and instantiates a character for each search result. This particular query does some funky stuff with the “let” keyword so I can “drill into” the <image><icon_url> nested elements and pull out an image URL or leave it null if neither XML tag is present.

No doubt it’ll be a while before I get everything working the way I want (particularly making the online functionality extensible via MEF), but this is a good first step. Kudos to the ComicVine guys for making their data available in such a flexible way!