In Part 1 of this series, we used App Studio to build the shell of a project that will (eventually) display data from a REST API call, specifically the Rotten Tomatoes API. In App Studio, we were able to create a dynamic collection, select the type of layout for its two pages (list and details), and then set the bindings for each of those pages without setting any actual data. Here in part 2, we are going to edit the source code generated from App Studio to then get our data from the Rotten Tomatoes API. If you would rather follow along by video, you can find the Youtube video here.
The Source Code
You should have finished part 1 by downloading the source code. If you have done so and unzipped the file you should see a Visual Studio solution file. Keep in mind, you will need Visual Studio 2013 update 2. Go ahead and open the .sln file highlighted below.
Once Visual Studio has loaded up you can take a look at the Solution Explorer for this list of projects and files. Notice that we have four different projects here; AppStudio.Windows, AppStudio.WindowsPhone, AppStudio.Shared, and AppStudio.Data. This is the general structure for a Windows Universal App, which supports Windows 8.1 and Windows Phone 8.1. That said, the first two projects contain files specific to those two respective platforms. Then there is the Shared project which holds files shared between the two platforms, and the Data project (a portable class library) which is where we will be focused today.
Below you can se the three highlighted files from within the Data project that we are going to be looking at today
First let’s take a look at the InTheatersSchema file. This is basically the object model for the data that we defined in our collection. You can see the four fields that we defined in App Studio; Title, Rating, ImageUrl, and Synopsis. Also, keep in mind, that the section that contains this collection in Part 1 was called “In Theaters”. This is why this file is called InTheatersSchema. It is the data schema for the “In Theaters” section. We won’t be editing this file, but it is worth mentioning where it comes from and making the connection.
From here, let’s move over to the ServiceDataProvider file. This file by default is used to access databases of a Dynamic Collection that we create in App Studio. However, since we wont be getting our data that way (we want data from Rotten Tomatoes), we could either change this file or create our own. Either way is fine, but to make things easier, I have added an updated ServiceDataProvider.cs file to my OneDrive. You can simply replace the file in your solution explorer with my updated one. Since all App Studio projects by default have the same solution name, the namespaces should work out okay here.
So, go ahead and replace the file. The best way to do this is to just drag the new file in and choose to replace the older file.
Now, let’s take a second to talk about what is happening here. In general, we need to…
- Call the Rotten Tomatoes API
- Deserialize that data
- Return the appropriate data type.
In looking at the code, the first things you will notice are your API Key string (which you will need to fill in) and several strings that represent different calls that we can make to Rotten Tomatoes. Again, make sure that you fill in your API Key here or none of the below calls will work.
private static string ROTTEN_TOMATOES_API_KEY = "";
private static string ROTTEN_TOMATOES_API_MOVIES_BOXOFFICE = @"http://api.rottentomatoes.com/api/public/v1.0/lists/movies/box_office.json?limit=20&country=us&apikey=" + ROTTEN_TOMATOES_API_KEY;
private static string ROTTEN_TOMATOES_API_MOVIES_INTHEATERS = @"http://api.rottentomatoes.com/api/public/v1.0/lists/movies/in_theaters.json?page_limit=20&page=1&country=us&apikey=" + ROTTEN_TOMATOES_API_KEY;
private static string ROTTEN_TOMATOES_API_MOVIES_OPENING = @"http://api.rottentomatoes.com/api/public/v1.0/lists/movies/opening.json?limit=20&country=us&apikey=" + ROTTEN_TOMATOES_API_KEY;
private static string ROTTEN_TOMATOES_API_MOVIES_UPCOMING = @"http://api.rottentomatoes.com/api/public/v1.0/lists/movies/upcoming.json?page_limit=20&page=1&country=us&apikey=" + ROTTEN_TOMATOES_API_KEY;
private static string ROTTEN_TOMATOES_API_DVD_TOPRENTALS = @"http://api.rottentomatoes.com/api/public/v1.0/lists/dvds/top_rentals.json?limit=20&country=us&apikey=" + ROTTEN_TOMATOES_API_KEY;
private static string ROTTEN_TOMATOES_API_DVD_CURRENTRELEASES = @"http://api.rottentomatoes.com/api/public/v1.0/lists/dvds/current_releases.json?page_limit=20&page=1&country=us&apikey=" + ROTTEN_TOMATOES_API_KEY;
private static string ROTTEN_TOMATOES_API_DVD_NEWRELEASES = @"http://api.rottentomatoes.com/api/public/v1.0/lists/dvds/new_releases.json?page_limit=20&page=1&country=us&apikey=" + ROTTEN_TOMATOES_API_KEY;
private static string ROTTEN_TOMATOES_API_DVD_UPCOMING = @"http://api.rottentomatoes.com/api/public/v1.0/lists/dvds/upcoming.json?page_limit=20&page=1&country=us&apikey=" + ROTTEN_TOMATOES_API_KEY;
For more information on how we formed this strings, you can check out my post on the Rotten Tomatoes API.
Now, let’s take a look at the three methods in this class, DownloadAsync, Load, and Copy.
DownloadAsync method which accepts a Uri as a parameter, and then uses an HttpClient to get and return the JSON string from our call. Pretty straight forward.
public async Task<string> DownloadAsync(Uri url)
HttpClient client = new HttpClient();
return await client.GetStringAsync(url);
The Load method that will get the data returned from DownloadAsync, use the Copy method (see below) to convert it. This load function will look pretty similar to the one from the original ServiceDataProvider.cs file (if you took a look before we replaced it). It makes a call to the Copy method (see below) and returns the list of data. One thing you can explore with here is the Rotten Tomatoes call in bold below. Currently, I am using the Box Office call which returns a list of movies in Box Office, but you can choose any of the ones that we added above.
public async Task<IEnumerable<T>> Load<T>()
string data = await DownloadAsync(new Uri(ROTTEN_TOMATOES_API_MOVIES_BOXOFFICE));
IEnumerable<T> records = (IEnumerable<T>)Copy(data);
catch (Exception ex)
The Copy method takes the JSON string response, deserializes it to a Dynamic object, and then copies that data to an ObservableCollection of InTheatersSchema objects. Remember us walking through the InTheaterSchema file earlier? Just to reiterate, that schema file will have a property for each column of our dynamic collection that we defined in App Studio.
public ObservableCollection<InTheatersSchema> Copy(string data)
dynamic foo = JObject.Parse(data);
ObservableCollection<InTheatersSchema> collection = new ObservableCollection<InTheatersSchema>();
foreach (dynamic movie in foo.movies)
InTheatersSchema temp = new InTheatersSchema();
temp.Title = movie.title;
temp.Rating = movie.year.ToString();
string image = movie.posters.original;
temp.ImageUrl = image.Replace("tmb", "ori");
temp.Synopsis = movie.synopsis;
The goal here was to make this method as generic as possible, so that with minimal changes, you could reference different APIs. HINT HINT. Stay tuned for future post on that
Now, let’s open up the InTheatersDataSource.cs. Two lines are highlighted below that create an instance of a ServiceDataProvider class and calls its load method. We only need to make one small change here; strip out the parameters when creating the new instance of ServiceDataProvider. We don’t have an explicit constructor in our updated version, so we can’t accept any parameters here.
Should now look like this.
**Additionally, we might need to add the following using statement to resolve the error on ServiceDataProvider.
Deploy to Windows 8.1
Go ahead and deploy to Windows 8.1, and you should see the following.
Additionally, if you click on one o the movies, you will see its details page.
Deploy to Windows Phone
You can also run it as a phone app in the phone emulator.
You might notice that the images don’t fit perfectly. You can go in and edit the layout accordingly. Additionally, check out Part 3, where I will show you how to incorporate any API that you want!
As always comment below with any questions, comments, or concerns and follow me on Twitter @jquickwit.