Seattle Movie Finder: An AJAX- and REST-Powered Virtual Earth Mashup
by Dare Obasanjo
|
Pages: 1, 2, 3, 4, 5
Building the Seattle Movie Finder Service
A core part of every AJAX application is the service on the web server with which the web browser communicates. In most AJAX applications this is a simple URL-based service from which XML or JSON can be retrieved and then parsed on the client using JavaScript. In my application I needed a URL endpoint that could provide me two classes of data: all the movies playing in the Seattle area, and information about the movie theaters showing a specific movie. Below is a screenshot of the web page showing both classes of information.

Figure 1. Screenshot of search results for "King Kong"
On the server side there are two primary methods of interest. The first is the GetMovies() method, which returns the list of movies currently playing in the Seattle area, and the other is the GetMovieListings() method, which returns the theaters currently showing a particular movie. Both methods return a MovieTheaters object which is then sent to the browser as serialized XML. Below is a definition of the MovieTheaters class and its related classes.
[System.Xml.Serialization.XmlRootAttribute("theaters", IsNullable=false)]
public class MovieTheaters{
[System.Xml.Serialization.XmlElementAttribute("theater", Type = typeof(MovieTheater), IsNullable = false)]
public ArrayList theaterList = new ArrayList();
}
public class MovieTheater{
public string name;
public string address;
[System.Xml.Serialization.XmlElementAttribute("lat")]
public double latitdue;
[System.Xml.Serialization.XmlElementAttribute("long")]
public double longitude;
[System.Xml.Serialization.XmlArrayAttribute(ElementName = "movies", IsNullable = false)]
[System.Xml.Serialization.XmlArrayItemAttribute("movie", Type = typeof(Movie), IsNullable = false)]
public ArrayList movieList = new ArrayList();
[System.Xml.Serialization.XmlIgnoreAttribute()]
public Uri url;
}
public class Movie{
public string name;
[System.Xml.Serialization.XmlArrayAttribute(ElementName = "times", IsNullable = false)]
[System.Xml.Serialization.XmlArrayItemAttribute("time", Type = typeof(System.String), IsNullable = false)]
public ArrayList times = new ArrayList();
}
The XML obtained from serializing an instance of the MovieTheaters class conforms to the XML schema provided in the previous section.
The information provided by the GetMovies() and GetMovieListings() methods is always at most one day old. However, instead of invoking an external service every time a user interacts with the Movie Finder page, the movie information is cached within the Seattle Movie Finder application unless it is over a day old, in which case external services are invoked.
The GetMovies() method is exposed as a RESTful web service by accessing the URL at http://www.25hoursaday.com/moviefinder/MovieFinder.aspx?showall=true. The code for the GetMovies() method is shown below.
private XmlDocument GetMovies(){
DateTime dateMovieListUpdated = DateTime.MinValue;
object mlu = Cache.Get("MovieListUpdated" );
if(mlu != null){
dateMovieListUpdated = (DateTime) mlu;
}
TimeSpan sinceLastUpdate = DateTime.Now.Subtract(dateMovieListUpdated);
TimeSpan oneDay = new TimeSpan( 1,0,0,0);
XmlDocument movies = (XmlDocument) Cache.Get("MovieList" );
if(sinceLastUpdate > oneDay){
movies = MoviesService.GetMovieList();
Cache["MovieListUpdated" ] = DateTime.Now;
Cache["MovieList" ] = movies;
}
return movies;
}
The GetMovieListings() method is exposed as a RESTful web service by accessing the URL at http://www.25hoursaday.com/moviefinder/MovieFinder.aspx?movie={0} where {0} is replaced with the name of the target movie such as http://www.25hoursaday.com/moviefinder/MovieFinder.aspx?movie=Firewall. The code for the GetMovieListings() method is shown below.
private void GetMovieListing( string movieName, XmlWriter writer){
DateTime dateMovieListingsUpdated = DateTime.MinValue;
object mlu = Cache.Get("MovieListingsUpdated");
if(movieName.ToLower().StartsWith("the ")){
movieName = movieName.Substring(4) + ", The" ;
}
if(mlu != null){
dateMovieListingsUpdated = (DateTime) mlu;
}
TimeSpan sinceLastUpdate = DateTime.Now.Subtract(dateMovieListingsUpdated);
TimeSpan oneDay = new TimeSpan(1,0,0,0);
if(sinceLastUpdate > oneDay){
theaters = MoviesService.FetchMovieListings();
Cache["MovieListingsUpdated"] = DateTime.Now;
Cache["MovieTheaters"] = theaters;
}
MovieTheaters mts = new MovieTheaters();
foreach(MovieTheater mt in theaters.theaterList){
foreach(Movie m in mt.movieList){
if(m.name == movieName){
MovieTheater mt2 = new MovieTheater();
mt2.name = mt.name;
mt2.address = mt.address;
mt2.latitdue = mt.latitdue;
mt2.longitude = mt.longitude;
Movie m2 = new Movie();
m2.name = m.name;
m2.times = m.times;
mt2.movieList.Add(m2);
mts.theaterList.Add(mt2);
break;
}
}
}
XmlSerializer serializer = new XmlSerializer( typeof(MovieTheaters));
serializer.Serialize(writer, mts);
}