Search Digg on Windows Phone 7

10 בפברואר 2011

אין תגובות

Following is another utility class I wrote to help me search Digg results asynchronously on a Windows Phone 7 application.

I will present how it was written and then how to use it. At the end of this post you can find a sample application that contains all the code.

digg search sample

How to Search Digg?

Define DiggStory

First we define a model class that will hold a single Digg entry. This class will have the following properties:

  • Title – title of the Digg entry
  • Description – description of the Digg entry
  • Link – link to the Digg entry
  • Diggs – number of diggs in Digg
/// <summary>
/// Model for Digg Story
/// </summary>
public class DiggStory
{
    /// <summary>
    /// Initializes a new instance of the <see cref="DiggStory"/> class.
    /// </summary>
    /// <param name="title">The title.</param>
    /// <param name="description">The description.</param>
    /// <param name="link">The link.</param>
    /// <param name="diggs">The diggs.</param>
    public DiggStory(string title, string description, string link, int diggs)
    {
        Title = title;
        Description = description;
        Link = link;
        Diggs = diggs;
    }

    /// <summary>
    /// Gets or sets the title.
    /// </summary>
    /// <value>The title.</value>
    public string Title { get; set; }

    /// <summary>
    /// Gets or sets the description.
    /// </summary>
    /// <value>The description.</value>
    public string Description { get; set; }

    /// <summary>
    /// Gets or sets the link.
    /// </summary>
    /// <value>The link.</value>
    public string Link { get; set; }

    /// <summary>
    /// Gets or sets the diggs.
    /// </summary>
    /// <value>The diggs.</value>
    public int Diggs { get; set; }
}

Add Assembly

In the following implementation I use Digg Search API which returns XML based results, so I‘m using LINQ to XML to easily parse the output.

In order to do so, we will add a reference to the assembly System.Xml.Linq.dll

add reference system.xml.linq

Generate Application Key

Like most service providers, Digg also requires you to generate an application key for your application. This helps them know who uses their service and allow them to limit the requests from a single consumer.

I found the following application key to work, but I suggest you find a way to generate a new one in commercial apps.

private const string DiggApplicationKey = "http://www.myapp.com";

Implement the Digg Search Service

Querying the Digg service is rather easy. Just use the following link:

http://services.digg.com/search/stories?query={0}&appkey={1}

Where {0} should be replaced with your search term and {1} should be replace with your application key.

So our Search method will receive the search term as a parameter.
In addition, since we want our class to work asynchronously we will accept as parameters a few more delegates:

  • Action<IEnumerable<DiggStory>> onSearchCompleted, which will be called when the Digg results are ready to be processed.
  • Action<string, Exception> onError, which will be called if there is an error while searching Digg. The first parameter for the delegate is the search term and the second is the exception.
  • Action onFinally, which will be called always, whether there was an exception or not. Think of it as the finally section on a common try-catch block.

So the method signature will be:

public static void Search(string searchText, Action<IEnumerable<DiggStory>> onSearchCompleted = null, Action<string, Exception> onError = null, Action onFinally = null)

To run the search we will use the WebClient class:

WebClient webClient = new WebClient();

// register on download complete event
webClient.DownloadStringCompleted += delegate(object sender, DownloadStringCompletedEventArgs e)
{
    …
};

// start search
webClient.DownloadStringAsync(new Uri(string.Format(DiggSearchQuery, searchText, DiggApplicationKey)));

where DiggSearchQuery is defined as follows:

private const string DiggSearchQuery = "http://services.digg.com/search/stories?query={0}&appkey={1}";

 

The result of the search is an XML string, so we use LINQ to XML to parse it:

// convert xml result to model
XElement storyXml = XElement.Parse(e.Result);

var stories = from story in storyXml.Descendants("story")
              select new DiggStory(
                  story.Element("title").Value,
                  story.Element("description").Value,
                  story.Attribute("link").Value,
                  int.Parse(story.Attribute("diggs").Value));

The rest of the code handles the different delegates: onCompleted, onError, onFinally. I bring here the method in its full:

/// <summary>
/// Searches the specified search text.
/// </summary>
/// <param name="searchText">The search text.</param>
/// <param name="onSearchCompleted">The on search completed.</param>
/// <param name="onError">The on error.</param>
public static void Search(string searchText, Action<IEnumerable<DiggStory>> onSearchCompleted = null, Action<string, Exception> onError = null, Action onFinally = null)
{
    WebClient webClient = new WebClient();

    // register on download complete event
    webClient.DownloadStringCompleted += delegate(object sender, DownloadStringCompletedEventArgs e)
    {
        try
        {
            // report error
            if (e.Error != null)
            {
                if (onError != null)
                {
                    onError(searchText, e.Error);
                }
                return;
            }

            // convert xml result to model
            XElement storyXml = XElement.Parse(e.Result);

            var stories = from story in storyXml.Descendants("story")
                            select new DiggStory(
                                story.Element("title").Value,
                                story.Element("description").Value,
                                story.Attribute("link").Value,
                                int.Parse(story.Attribute("diggs").Value));

            // notify completed callback
            if (onSearchCompleted != null)
            {
                onSearchCompleted(stories);
            }
        }
        finally
        {
            // notify finally callback
            if (onFinally != null)
            {
                onFinally();
            }
        }
    };

    // start search
    webClient.DownloadStringAsync(new Uri(string.Format(DiggSearchQuery, searchText, DiggApplicationKey)));
}

Using the Digg Search Service

Using the class is very easy, just pass the required search term and a delegate for the “completed” notification.

DiggService.Search(
    textbox.Text,
    (items) => { listbox.ItemsSource = items; },
    (s, exception) => { MessageBox.Show("Search term " + s + " could not be found due to:\n" + exception.Message); },
    null
    );

There is a sample application which can be downloaded here.

Note: this code was first published as part of the “Using Pivot and Panorama Controls” lab found in the Windows Phone Training Kit for Developers, which I wrote for Microsoft.

That’s it for now,
Arik Poznanski.

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. (*) שדות חובה מסומנים