Free Trial

Safari Books Online is a digital library providing on-demand subscription access to thousands of learning resources.

  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • PrintPrint

Talking to Flickr

Talking to Flickr Applies to Silverlight 3, 4 and 5 There are quite a few large websites out there that expose (part of) their functionality through services, most of the time through the use of RESTful services. A great example is Flickr (www.flickr.com). Flickr exposes many services that allow searching for pictures, tagging existing pictures, uploading pictures, and so on. We can leverage all the goodness that Flickr provides inside our applications to provide more functionality to our end users. Note Flickr is a popular website where people can upload and share images and videos. Apart from viewing this content on the site, Flickr offers a wide range of services for interaction with its content. Currently, Flickr has millions of users sharing several billion images! One thing that is very important is the open crossdomain.xml file that Flickr exposes. It allows connecting from every domain (so also from a Silverlight application running locally). This is why we can connect directly from Silverlight to Flickr. However, most Web 2.0 websites aren't that open, for example, Twitter. Communication with such a service from Silverlight is explained in the following recipe. Note that not all code for this sample is printed in this book. Refer to the code in the downloadable samples for this. Getting ready Most sites that expose public services, such as Flickr, Amazon, Digg, and so on, allow us free access to their services, however, you'll often need to register to get a key/identification. This is then used by the issuing site to track where the call came from. Some services allow only a limited number of calls for a particular key within a certain time span to discourage overuse. For the code in this recipe, you'll need a Flickr API key, which can be obtained for free from http://www.flickr.com/services/api/keys/. This key can be pasted in the sample code that can be downloaded for this book. The recipe uses a WrapPanel—a control that's part of the Silverlight Control Toolkit. The toolkit is a collection of controls and extensions on Silverlight. This can be obtained from www.codeplex.com/silverlight. See Appendix D for more information on the Silverlight Control Toolkit. To follow along with this recipe, a starter solution has been provided in the Chapter10/SilverFlickr_Starter folder in the code bundle available on the Packt website. The completed solution for this recipe can be found in the Chapter10/SilverFlickr_Completed folder. How to do it... In this recipe, we'll build a simple application that allows us to search for photos based on a search term that the user can enter. On clicking on one of the results, the details of the photo are shown. For this, the application uses two of the many methods available from Flickr, namely flickr.photos.search and flickr.photos.getinfo. These methods allow searching for photos matching a search string and getting more information on a photo, respectively. To begin building this application, we'll need to complete the following steps: Open the starter solution as outlined in the Getting ready section. This is an empty solution with some assets already in place.As we are going to use REST services, we'll be making use of the WebClient class. This class resides in the System.Net namespace, which is part of the System.Net assembly. If you're using Visual Studio 2008 (for building/maintaining a Silverlight 3 project), you need to add a reference to this assembly yourself. Visual Studio 2010 refers to this assembly by default for new projects.The XAML code for the UI of the application is quite easy to understand. A StackPanel resides at the top of the page, containing an Image, a TextBox to enter the search query, and a Button. The page also contains a ScrollViewer with a WrapPanel (part of the Silverlight Control Toolkit, refer to the Getting ready section of this recipe) on the left. The XAML code for this is as follows: <Grid x:Name="LayoutRoot" Background="White"> <Grid.RowDefinitions> <RowDefinition Height="50"></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="300"></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <StackPanel Grid.Row="0" Grid.Column="0" HorizontalAlignment="Left" Orientation="Horizontal" Grid.ColumnSpan="2"> <Image Source="flickr.png" Stretch="None" Margin="3 0 0 0" > </Image> <TextBox x:Name="SearchTextBox" Width="200" Height="30" M </TextBox> <Button x:Name="SearchButton" Content="Search Flickr" Click="SearchButton_Click" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5"> </Button> </StackPanel> <ScrollViewer Grid.Row="1" Grid.Column="0" Background="DarkGray"> <toolkit:WrapPanel x:Name="ResultPanel" HorizontalAlignment="Center"> </toolkit:WrapPanel> </ScrollViewer> </Grid> As mentioned before, Flickr's API is a REST API. Thus, we need to send a request to a specific URI and read out the response being sent back. Let's first take a look at the URI. As defined by Flickr, this URI needs to be in a specific format. As we'll be doing a search, we'll use the flickr.photos.search method. It requires two parameters: your personal API key and the search term entered in the search field. This is shown in the following code: string api_key = "123456";//TODO: replace with your own key string searchUrl = "http://api.flickr.com/services/rest /?method=flickr.photos.search&api_key={0}&text={1}"; We now have the URI; we can use it to send a request. To send this request, we'll use the WebClient class again. In the Click event handler of the button, we'll create an instance of this class. We need to register the callback method via DownloadStringCompleted and send the request using DownloadStringAsync, passing in the URI as a parameter. As with other services, these calls are asynchronous. This is shown in the following code: private void SearchButton_Click(object sender, RoutedEventArgs e) { WebClient client = new WebClient(); client.DownloadStringCompleted += new DownloadStringCompletedEventHandler (client_DownloadStringCompleted); client.DownloadStringAsync(new Uri(string.Format(searchUrl, api_key, SearchTextBox.Text))); } In the callback, we have access to the result of the call via the Result property on the instance of DownloadStringCompletedEventArg. The response is plain XML, formatted by Flickr in a specific format. We'll use LINQ-To-XML to parse this XML code and create a list of ImageInfo objects (shown in the following code), a custom type defined to have typed access to our data in the Silverlight application. Note that the ImageUrl implementation creates the link to the image as used by Flickr. Add the following class to the Silverlight project: public class ImageInfo { public string ImageId { get; set; } public string FarmId { get; set; } public string ServerId { get; set; } public string Secret { get; set; } public string ImageUrl { get { return string.Format ("http://farm{0}.static.flickr.com/{1}/{2}_{3}_m.jpg", FarmId, ServerId, ImageId, Secret); } } } Add a reference to the System.Xml.Linq assembly inside the Silverlight project.Finally, each ImageInfo instance is used to dynamically create an image and add it to the WrapPanel. Every image also gets a click event attached to it, which is used to open the detail page. This is shown in the following code: void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { XDocument xml = XDocument.Parse(e.Result); var photos = from results in xml.Descendants("photo") select new ImageInfo { ImageId = results.Attribute("id").Value.ToString(), FarmId = results.Attribute("farm").Value.ToString(), ServerId = results.Attribute("server").Value.ToString(), Secret = results.Attribute("secret").Value.ToString() }; foreach (var image in photos) { Image img = new Image(); BitmapImage bmi = new BitmapImage(new Uri(image.ImageUrl, UriKind.Absolute)); img.Source = bmi; img.Width = 200; img.Height = 200; img.Stretch = Stretch.Uniform; img.Tag = image; img.Margin = new Thickness(3); img.HorizontalAlignment = HorizontalAlignment.Center; ResultPanel.Children.Add(img); } } At this point, we can search Flickr for images. The following screenshot shows the finished application. Note that this final application includes extra code that allows clicking an image and viewing its details. However, the code for this is very similar and can be found in the code bundle: How it works... Communicating with Flickr's REST services is, in fact, no different from communicating with a self-created REST service, as was done in the beginning of this chapter. The URI is created according to the specifications given by the Flickr API. At http://www.flickr.com/services/api, you can find an overview of all the methods exposed by Flickr, varying from searching for pictures and reading out comments to finding pictures based on a location. For this recipe, we use the flickr.photos.search and flickr.photos.getinfo methods. Both require the API key sent as a parameter, apart from the specific parameters depending on the method. The format of the XML sent by Flickr's services is fixed. It's safe to build our code around this API, as the format can be considered to be a contract between the service and the client application. The service will always return the response formatted according to this specification. The following is the XML structure used by Flickr: <rsp> <photos> <photo id="1234567890" secret="0987654321" server="1234" farm="1" /> </photos> </rsp> There's more... Communication with the services exposed by Flickr from Silverlight is possible, because Flickr has a crossdomain.xml file in place that allows calls from any domain, as explained in the introduction of the recipe. The following is the complete crossdomain.xml (http://api.flickr.com/crossdomain.xml) file of Flickr. Refer to the Configuring cross-domain calls recipe in Chapter 7, Working with Services, for more information on the concept of cross-domain calls. <?xml version="1.0" ?> <!DOCTYPE cross-domain-policy (View Source for full doctype...)> <cross-domain-policy> <allow-access-from domain="*" secure="true" /> <site-control permitted-cross-domain-policies="master-only" /> </cross-domain-policy> However, other sites don't open up their API as much as Flickr does. A good example is Twitter (http://twitter.com/crossdomain.xml), which allows calls only from particular domains. This can be seen in the following code: <?xml version="1.0" encoding="UTF-8" ?> <cross-domain-policy xmlns:xsi="http://www.w3.org/2001/ XMLSchema-instance" xsi:noNamespaceSchemaLocation= "http://www.adobe.com/xml/schemas/ PolicyFile.xsd"> <allow-access-from domain="twitter.com" /> <allow-access-from domain="api.twitter.com" /> <allow-access-from domain="search.twitter.com" /> <allow-access-from domain="static.twitter.com" /> <site-control permitted-cross-domain-policies="master-only" /> <allow-http-request-headers-from domain="*.twitter.com" headers="*" secure="true" /> </cross-domain-policy> The consequence of such a crossdomain.xml file is that Silverlight can't connect directly with these services. The solution is creating an extra service on the same domain as the Silverlight application, which will in turn call the REST services. Your application then only has to connect with the new service, which shouldn't be a problem. We'll look at this scenario in the following recipe. A second possible solution is building a trusted Silverlight application, which we'll look at in the last recipe of this chapter. Flickr... more information The accompanying code for this book also contains the code to create the detail screen. For this, we can use another method, namely flickr.photos.getinfo, to retrieve more information about an image based on the photo ID. Displaying the values is done through the use of data binding. The DataContext property of the grid, located in the Details portion of the interface, is set to an instance of another type called ImageDetail. One particularity is certainly worth mentioning here - data binding the image is done through the use of a converter. The link to the image is stored as a Uri in the instance of ImageDetail. However, binding in XAML expects a BitmapImage. The conversion of type A to type B is done through the use of a converter—a class that implements the IValueConverter interface. This interface has two methods—Convert and ConvertBack. This is shown in the following code: public class ImageConverter:IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (value != null) return new BitmapImage((Uri)value); else return "";//can be link to a "NoImage.png" of some kind } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { } } See also In the Reading data from a REST service and Parsing REST results with LINQ-To-XML recipes from this chapter, we go deeper into the details of communication with a REST service. The following recipe shows the scenario to connect with services that don't allow cross-domain calls. For more information on data binding, refer to the recipes in Chapter 2, An Introduction to Data Binding, and Chapter 3,Advanced Data Binding.

  

You are currently reading a PREVIEW of this book.

                                                                                                                    

Get instant access to over $1 million worth of books and videos.

  

Start a Free Trial


  
  • Safari Books Online
  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • PrintPrint