Data Binding Part 5- Dynamic Data from Rotten Tomatoes

In Part 1 of this series I covered the basic theoretical idea behind data binding, and in Part 2, we got a little more concrete with a hands on example in code.  We created a Movie class, then bound the three properties of that object (title, rating, year), to our UI in both Windows and Windows Phone projects using a Universal Windows App.  Then, in Part 3, we took a look at implementing the INotifyPropertyChanged interface and the difference in OneWay and TwoWay binding.  In Part 4, we took it one step further.  Instead of just displaying one movie to our UI, we bound a list of static movies using ListView and ObservableCollection.  Now, we are going to display a list of dynamics movie data powered by the Rotten Tomatoes API.

If you are not familiar with Rotten Tomatoes you can check out the site, Rotten Tomatoes.  In general, Rotten Tomatoes is a go to source for movies; what’s in theaters, what’s new on dvd, what’s new on TV, etc..  With their API, you can make a call to RT and they will send you back a list of movies with numerous properties (ratings, synopsis, urls to posters, etc.).  Is it starting to click how this information might fit what we are working on here?  You know, binding a list of movies to our UI and what not.  It’s a perfect fit!

To work with the RT API, you will need to sign up and get an API key from their developers website.  After you do that, you can also check out the documentation for the API itself.  I won’t cover it in depth here -you can read into it yourself- but the concept is simple.  Make a call with a url, and RT sends you back a list of movies.  For starters, the base URI is https://api.rottentomatoes.com/api/public/v1.0. From there you can tack on your specific search and your API key.  A great way to get started with this is use the IO-Docs page, which allows you “try” different requests and see what is returned.  I highly recommend trying a few of these before moving on.

Capture8

Just as a reference, in this example, I will be using the following request Uri, that will ask for a list of 16 movies in the box office in the United States. Obviously, you will need to replace [your-api-key] with your actual API key.

https://api.rottentomatoes.com/api/public/v1.0/lists/movies/box_office.json?limit=16&country=us&apikey=[your-api-key]

Now that we know a little bit about the RT API.  Let’s think about how we are going to use the JSON response that it sends us back.  The general idea is to make an HTTP request to the above url and convert that JSON string into a usable object in c#.  Therefore, we need to define an object that matches the model provided in the JSON response.  This might sound tedious since there are nested objects returned in each given query, but there’s hope in the form of a website called json2csharp.  With this website, you can simply give it a url that will return a json response, and it will generate the appropriate C# classes for us!  Trust me, this is great news and saves us a ton of time!

Capture10

Input the url above with your app id, and you will see the classes generated as below.

Capture9

If you scroll all the way down you can see the class for the root object, which is where we find the list of Movie objects as well as some links.

Capture11

Let’s now create a new class in our Shared project called RottenTomatoes.cs. We will simply copy all of the classes we just generated into our new RottenTomatoes class while making a few small changes.  I am going to take the properties of the RootObject and make them properties of RottenTomatoes class, and get rid of the RootObject class completely.  Then, I am going to rename the Movie class within our RottenTomatoes class to RTMovie to differentiate itself from the Movie class that we have worked with in the previous posts.  After I do all of this, my new class looks like this.

class RottenTomatoes
    {
         public List<RTMovie> movies { get; set; }
        public Links2 links { get; set; }
        public string link_template { get; set; }

        public class ReleaseDates
        {
             public string theater { get; set; }
            public string dvd { get; set; }
        }

        public class Ratings
         {
            public string critics_rating { get; set; }
             public int critics_score { get; set; }
            public string audience_rating { get; set; }
            public int audience_score { get; set; }
        }

        public class Posters
        {
            public string thumbnail { get; set; }
             public string profile { get; set; }
            public string detailed { get; set; }
            public string original { get; set; }
        }

        public class AbridgedCast
         {
            public string name { get; set; }
            public string id { get; set; }
            public List<string> characters { get; set; }
        }

        public class AlternateIds
        {
            public string imdb { get; set; }
         }

        public class Links
        {
            public string self { get; set; }
            public string alternate { get; set; }
            public string cast { get; set; }
             public string clips { get; set; }
            public string reviews { get; set; }
            public string similar { get; set; }
        }

        public class RTMovie
        {
             public string id { get; set; }
            public string title { get; set; }
            public int year { get; set; }
             public string mpaa_rating { get; set; }
            public int runtime { get; set; }
            public string critics_consensus { get; set; }
            public ReleaseDates release_dates { get; set; }
            public Ratings ratings { get; set; }
            public string synopsis { get; set; }
            public Posters posters { get; set; }
            public List<AbridgedCast> abridged_cast { get; set; }
            public AlternateIds alternate_ids { get; set; }
            public Links links { get; set; }
        }

        public class Links2
        {
            public string self { get; set; }
            public string alternate { get; set; }
        }
     }

Whew.  Ok we have the model for our RottenTomatoes object created, now we need to go our and get the response.  We will do this in our MoviesDataSource.cs file that we created in the last post.  In the LoadData() method, we will replace the static data with dynamic data from RT.  First let’s go ahead and create a constant string in this class for our url and call it API_CALL;

private const string API_CALL = "https://api.rottentomatoes.com/api/public/v1.0/lists/movies/box_office.json?limit=16&country=us&apikey=[your-api-key]";

The next step is to make the http call to that url using an instance of HttpClient class.  Since we will be using the getStringAsync method of the HttpClient class, our loadData() method will now need to be marked as Async.  We will then “await” that response and assign it to a string variable.  So far out method looks like this.

async private void loadData()
{
            HttpClient wc = new HttpClient();
             string response = await wc.GetStringAsync(API_CALL);
}

**If you aren’t familiar with Asynchronous programming, you can read up Here.**

We have our JSON response stored in the string called response, so now we need to convert that string to an instance of our RottenTomatoes object.  To do this, we will use a NuGet package called json.net.  To add a reference to this package, in your Solution Explorer right click on your solution and then Manage NuGet Packages.  Search for Json.net and click install.  If done successful, you should see it show up in your Windows and Windows Phone projects under the References folder as “Newtonsoft.Json” like so.

Capture12

With the reference to json.net we can use to now convert our json string and cast it to an instance of our RottenTomateos class with one line.

RottenTomatoes rt = (RottenTomatoes)JsonConvert.DeserializeObject<RottenTomatoes>(response);

Great now we have a RottenTomatoes object with all sorts of data, but we are just binding to a collection of Movie objects.  So, the last step is to convert each of the movies in the RottenTomatoes object to a Movie object and add them to our ObservableCollection.  We can use a simple foreach to iterate over each RTMovie object from the list of movies in the RottenTomateos object.  As we iterate, we can create a temp Movie object and set its fields appropriately from the fields of the RTMovie.  Ok, I admit that sounds pretty tricky, but let me show you the code.

foreach (RottenTomatoes.RTMovie m in rt.movies)
           {
                Movie temp = new Movie();
               temp.Title = m.title;
               temp.Rating = m.mpaa_rating;
                temp.Year = m.year.ToString();
               this.Add(temp);
           }

Basically we are copying over all of the RTMovies as Movie objects since our UI was designed to bind to a Movie object.  We could have just easily changed the binding of our UI to bind to a list of RTMovie objects instead.  Either way works fine.  So, when I run my app one last time I see a dynamic list of movie data.

Screenshot (215)

Again, this may not look super fancy, but if you are looking for UI design, you’ll have to find someone much more creative and artistic than myself.  Anyways, I hope this makes sense and that this series has helped to give you a thorough understanding of data binding, when and how to use it, and how it benefits you as a developer.  Thanks for following along the way!

Feel free to follow me on twitter for upcoming posts! @jquickwit  As always comment with any questions, comments, or concerns below!