Friday, August 8, 2014

ASP.NET MVC External REST Models

If you have a web application that needs to make use of third party services, you may find it useful to make a local model for that object as you process it on the server site. For the example, I’m going to integrate the LibraryThing getwork response for my example application.
First, we want to model the information we want:

public class LTWork {
    public int Id {get; set;}
    public string Author {get; set;}
    public string Title {get; set;}
    public string Url {get; set;}
    public IEnumerable<string> Characters {get; set}
}
As you can see, we’re wanting the basic book stats (title, author, URL, and a list of characters). When we cann the site, we get a REST response that looks like this.
Now comes the time to parse it. Since it’s coming in as XML, we’ll want to parse the XML and extract the appropriate data. We’ll probably want to leverage this in a LibraryThing-specific service. Here’s our basic definition (we’re going to be using IoC containers):

public ILibraryThingService {
    LTWork GetWork(
        int? id, int? isbn, int? lccn, int? oclc, string title
    );
}
public LibraryThingService : ILibraryThingService {
    private static string Url = 
        "http://www.librarything.com/services/rest";
    private static string Version = "1.1";
    private static string ApiKey = "..."; // yeah right…
    private static string BaseUrlBuilder() {
        return String.Join("/", Url, Version);
    }
    private static string CommandUrl(
        string commandName, 
        params KeyValuePair<string, string> arguments
    ) {
        return BaseUrlBuilder() + "/?" 
            + String.Join("&", 
                commandName, 
                arguments.Select(x => x.Key + "=" + x.Value), 
                "apikey=" + ApiKey
            );
    }
    private static string GetResponse(string url) {
        if (String.IsNullOrEmpty(url)) {
            throw new ArgumentNullException(url);
        }
        using (WebClient client = new WebClient()) {
             return client.DownloadString(url);
        }
    }
    private static LTWork ParseWork(string data) {
        if (String.IsNullOrEmpty(data)) {
            throw new ArgumentNullException("data");
        }
        XDocument xdoc = XDocument.Parse(data);
        LTWork ltWork = new LTWork();
        ltWork.Id = Int32.Parse(
            xdoc.Descendants("item")
                .Attributes("id")
                .FirstOrDefault()
                .Value
        );
        ltWork.Author = xdoc.Descendants("author")
            .FirstOrDefault().Value;
        ltWork.Title = xdoc.Descendants("title")
            .FirstOrDefault().Value;
        ltWork.Url = xdoc.Descendants("url").FirstOrDefault().Value;
        ltWork.Characters = xdoc.Descendants("field")
            .Where(x =>
                x.Attribute("type").Value == "3"
                && x.Attribute("name").Value == "characternames"
            )
            .SelectMany(x => x.Elelements("fact").Value);
        return ltWork;
   }
    public LTWork GetWork(
        int? id, int? isbn, int? lccn, int? oclc, string title
    ) {
        if (
            id == null 
            && isbn == null 
            && lccn == null 
            && oclc == null 
            && String.IsNullOrEmpty(title)
        ) {
            throw new ArgumentException(
                "Must specify at least one parameter"
            );
        }
        List<KeyValuePair<string, string>> arguments = 
            new List<KeyValuePair<string, string>>();
        if (id != null) {
            arguments
                .Add(new KeyValuePair("id", id.Value.ToString()));
        }
        if (isbn != null) {
            arguments
                .Add(new KeyValuePair("isbn", isbn.Value.ToString()));
        }
        if (lccn != null) {
            arguments
                .Add(new KeyValuePair("lccn", lccn.Value.ToString()));
        }
        if (oclc != null) {
            arguments
                .Add(new KeyValuePair("oclc", oclc.Value.ToString()));
        }
        if (!String.IsNullOrEmpty(title)) {
            arguments.Add(new KeyValuePair(
                "title", title.Value.Replace(' ', '+')
            ));
        }
        string url = CommandUrl("librarything.ck.getwork", arguments);
        string response = getResponse(url);
        return ParseWork(response);
    }
}
Whew. That looks right…
Okay, so what that’s going to do is send the request to the server, get back a chunk of XML, and then parse out work info and the list of characters from the XML body, then present it in the model. If you so desire, you could then store this to your own database, or just present it life, whatever works best for you and your application (and of course the LibraryThing API terms of service).
If you’re doing this with a JSON API, it’s much easier, but that’s for a different article.

Thursday, August 7, 2014

Top 10 Recent Original Films

Every year, the powers that be[1] compile the list of top 10 grossing films. For this article, I am going to traverse backwards through these lists and list the “top 10 original films,” that is, films that are not:
  • A sequel/prequel
  • A remake
  • Based on a book/comic book
  • Based on a TV series
  • Based on a real-life event
  • Based on a video game[2]
  • Based on a theme park attraction
  • Based on a toy line
  • stuff like that…
So, here goes…

1. Gravity (2013, Dir. Alfonso CuarĂ³n)

This is a movie in which George Clooney and Sandra Bullock get stranded in space. I don’t think it’s loosely based on Lost in Space, so I’m pretty sure it counts. I had to navigate past Frozen (The Snow Queen by Hans Christian Anderson), Iron Man 3 (sequel to Iron Man 2, and based on the Iron Man comic series), Despicable Me 2 (sequel to Dispicable Me), The Hobbit: The Desolation of Smaug (based on The Hobbit by J. R. R. Tolkien, and a sequel to The Hobbit: An Unexpected Journey), The Hunger Games: Catching Fire (based on Catching Fire by Suzanne Collins, which is the second book in the Hunger Games series; likewise, this movie is a sequel to the film adaptation of The Hunger Games), Fast & Furious 6 (Sequel to Fast Five, part of The Fast and the Furious film series), and Monsters University (prequel to Monsters, Inc.)

2. Inception (2010, Dir. Christopher Nolan)

This movie is about people who steal things from people’s dreams. It’s not based on Hamlet’s soliloquy. “What dreams may come...”I had to navigate past Man of Steel (Superman film), and Thor: The Dark World (sequel and based on comic series, and part of the Marvel Cinematic Universe), every top ten movie in 2012 (The Avengers, Skyfall, The Dark Knight Rises, The Hobbit: An Unexpected Journey, Ice Age: Continental Drift, The Twilight Saga: Breaking Dawn - Part 2, The Amazing Spider-man, Madagascar 3: Europe’s Most Wanted, The Hunger Games, and Men in Black 3), every top ten movie in 2011 (Harry Potter and the Deathly Hallows - Part 2, Transformers: Dark of the Moon, Pirates of the Caribbean: On Stranger Tides[3], The Twilight Saga: Breaking Dawn - Part 1, Mission: Impossible - Ghost Protocol, Kung Fu Panda 2, Fast Five, The Hangover Part II, The Smurfs, and Cars 2), Toy Story 3, Alice in Wonderland, and Harry Potter and the Deathly Hallows.

3. Despicable Me (2010, Dir. Pierre Coffin & Chris Renaud)

I’m pretty sure that the “story” that Sergio Pablos wrote was specifically for this film, but I’m unable to find any information indicating either way. This is about a typical “evil genius” who must balance his life of evil geniusdom with raising three kids. I only had to navigate past Shrek Forever After, The Twilight Saga: Eclipse, Iron Man 2, and Tangled.

4. Avatar (2009, Dir. James Cameron)

While some have said that this film is essentially Dancing With Smurfs, it does not claim to owe its origin to any outside source, and that’s what counts for this article.
I only had to get past How to Train Your Dragon. Lucky me.

5. 2012 (2009, Dir. Roland Emmerich)

While this movie does owe some of its origin to our misperception of the Mayan long-count calendar, and the writings of Al Gore, it doesn’t seem to actually be based on anything that came before it. We got here after rushing past Harry Potter and the Half-Blood Prince, Ice Age: Dawn of the Dinosaurs, and Transformers: Revenge of the Fallen.

6. Up (2009, Dir. Pete Docter)

Leave it to Pixar to make an original film, every other film. This was, to date, the saddest Pixar film I’ve ever seen, but it also got nominated for an academy award for best picture (to date, only three animated films, all Disney, have been nominated for this award). I didn’t have to navigate past anything, except the bucket of tears the first five minutes of this film brought.

7. The Hangover (2009, Dir. Todd Phillips)

While the subject of getting drunk and doing crazy things only to have to piece them together later on has been around since Hunter S. Thompson, this movie owes its origin to no discernable work that came before it, and as such is “original.” To get here (...yay...) I had to get past The Twilight Saga: New Moon, Sherlock Holmes, and Angels & Demons).

8. Kung Fu Panda (2008, Dir. John Stevenson & Mark Osborne)

This film tells the tale of an anthropomorphic pandabear that learns kung fu. What makes this movie particularly interesting is that the animals adopt the kung fu style named after them. Nice move, DreamWorks. I had to get past The Dark Knight and Indiana Jones and the Kingdom of the Crystal Skull to get here.

9. Hancock (2008, Dir. Peter Berg)

A superhero movie that did not require a comic book to come before it. It came in right after Kung Fu Panda.

10. WALL-E (2008, Dir. Andrew Stanton)

Once again, Pixar gives us another original film (though some might argue that it’s My Fair Lady with robots and the obese…). I hear a lot of criticism of this film, saying “The first half was good...” I don’t get it. I love this movie all the way through. To get here, I had to get past Mamma Mia!, Madagascar: Escape 2 Africa, Quantum of Solace, and Iron Man.
Whew. That was a lot of work. I had to go back about 6 years to get all 10. Also, based on the current standings for 2014, I don’t think we’ll see another “original” movie until that Public Domain thing starts kicking in again. I’m glad I didn’t go for 20, or else, I’d probably have to go back to the eighties (checking, 2007 - 1, 2006 - 2, 2005 - 3, 2004 -2, 2003 - 2, okay, not exactly the eighties).
So the valuable take-away from all of this is: if you want to be a commercial success, don’t be original. Wait, that’s not the lesson I want people to learn! The take-away is: I want more original movies. They’re better, even if they aren’t more commercially successful. The only reason more people watch the less original films is because they’re familiar. Let’s take away familiarity for just a year, or a summer or a “holiday season”, and let’s see if we can have a top 10 that’s all new material.
Please?

[1] Box Office Mojo
[2] This check is essentially a no-op
[3] Not only a sequel in a series based on an attraction at Disney World, but also based on an unrelated pirate book by Tim Powers.