A Silverlight Bing API Web Application: Server side (Part 2)

This is part 2 of the A Silverlight Bing API Web Application walk-through.

Silverlight development

What I found instantly using Silverlight was that development was identical to developing a typical web application using ASP.net. One core difference was that whereas ASP.net uses XHTML to design the UI of the web content, Silverlight utilizes Extensible Application Markup Language (XAML). The layout and structure of both languages are identical in terms of XML formatting. Furthermore, both technologies has support for server side implementation via higher level programming languages such as VB and C#. Each XAML page has a server side code associated with it, and this is code which is essentially fired on the server.

However in XAML html tags such as bold, italic and so on cannot be used.

XAML

E.g.

    
    <TextBlock x:Name="txtString" FontSize="20" Foreground="Black"></TextBlock>

Here Canvas is a UI element which is basically a container similar to a HTML div. A UI component called TextBlock is also present with additional attributes:

x:Name = the unique identifier to reference the TextBlock from server side code. FontSize = the font size of the text entered inside the TextBlock text-field. Foreground = the brush color of the text. Text = the pre-defined text which is inserted into the TextBlock text-field at run-time.

In my solution I have two XAML pages.

XAML Page 1: MainPage.xaml - a simple text box with button

XAML Page 2: Results.xaml - this page displays the Bing Results from the API.

Server side code C#

Helper classes I created a few helper classes which enabled the encapsulation of the Bing API Image, Video and Web results. These helper classes reflected the properties typically found within a response from the API.

Example of the Bing API Web Result Response in JSON (shortened version):

  Results: [
             
             -
             {
                Title: "Apple (United Kingdom)"
                Description: "Official site for Macintosh products in the UK.
                              Products, store, support and dealer list."
                Url: http://www.apple.com/uk/
                CacheUrl: http://cc.bingj.com/cache.aspx?
                          q=apple&d=76651518509612&w=590d19f6,
                          37350c43
                DisplayUrl: "www.apple.com/uk"
                DateTime: "2009-09-01T13:56:27Z"
           

Example of the properties of the Bing API Web Result class:

    
    private string Title;
    private string Description;
    private string Url;
    private string CacheUrl;
    private string DisplayUrl;
    private DateTime dateTime;

Asynchronous model + Silverlight

When you are first developing the server side code of a Silverlight application it is ** important to note that the Silverlight UI runs on one single thread **. The reason behind is that Silverlight does not block wait on an HTTP or Socket call. Therefore Silverlight does not block the UI of the web-browser. That is why Silverlight is developed on the asynchronous model.

If you have a look at the WebClient or the WebRequest class you will see that there is no way to synchronously download content.

The methods: BeginGetRequestStream() BeginGetResponse() EndGetRequestStream() EndGetReponse()

…are all Asynchronous methods

This means that a majority of coding especially network related communication needs to incorporate the asynchronous model.

Once the asynchronous web request has been made to the Bing API, parsing the JSON web response using the JSON Classes is the next step to take:

Json Class usage

    
    L1 private void processBingJSONResults(string json_results)
    L2 {
    L3   try
    L4   {
    L5     JsonValue bing_results = JsonValue.Parse(json_results);
    L6     JsonValue bing_web_result;
    L7     JsonArray bing_results_array = null;
    L8     if (bing_results.ContainsKey("SearchResponse"))
    L9       bing_results = bing_results["SearchResponse"];
    L10    if (bing_results.ContainsKey("Web"))
    L11    {
    L12      bing_web_result = bing_results["Web"];
    L13      if (bing_web_result.ContainsKey("Results")) //found results
    L14      {
    L15        bing_results_array = (JsonArray)bing_web_result["Results"];
    L16        if (bing_results.Count > 0)
    L17        {
    L18           for (int i = 0; i < bing_results_array.Count; i++)
    L19           {
    L20             JsonValue bingResultElement = bing_results_array[i];
    L21             BingWebResult bingResult = new BingWebResult();
    L22             if (bingResultElement.ContainsKey("Title"))
    L23               bingResult.BingResultTitle =
    L24               bingResultElement["Title"].
    L25               ToString().Replace("\"", string.Empty);
    L26           }
    L27         }
    L28       }
    L29     }
    L30   }
    L31   catch(Exception e)
    L32   {
    L33   }
    L34 }

Code breakdown

L1: The method above takes a string object called ‘json_results’ which is the response taken from the API’s web response to the request sent  out earlier.

L5: The JsonValue abstract class is used to parse the string object ‘json_results’ into a serialized object compatible with the Common Language Runtime (CLR), and stored in the variable ‘bing_results’.

The JsonValue is an abstract base class for Json, the structure of the collection it utilizes is based on KeyValuePair(TKey, TValue).

So going back to our Bing API JSON response the keys would be:

SearchResponse Version Query Web Results

The values would be those values associated with these keys dependent on the actual API JSON response.

L8: The reason why I check to see whether the variable ‘json_results’ has a certain key is in order to keep ‘digging’ deeper until the actual web results are reached.

L13: Once the Results key is reached and found we can be almost be certain that there will be some results to be seen. That is where the JsonArray, (an ordered sequence of JsonValue objects) comes into play.

L18 - L26: Iterate through the array and populate a specialized list container to add a new Object of type Bing API Web Result.

After parsing the JSON data

You cannot simply display the Web results back to the user in the Silverlight application,  since the web response from the Microsoft Bing API was requested asynchronously. This means that we need to create a delegate (reference to an object in this case a method) to handle the displaying of the Bing data.

As mentioned earlier I have 2 XAML pages one allowing the user to search for a term and the other page which displays the web results. The results page is called Results.xaml.

As soon as the method which parses the JSON response from the web-server is completed the Silverlight application navigates to the next XAML page where the data is displayed to the user in the UI.


   processBingJSONResults(stringContent);
   showResults r = new showResults(showResultsPage);
   this.Dispatcher.BeginInvoke(r, new object[]
   {
    BingWebResults
   });

Since Silverlight UI runs on one single thread, a delegate need to be created in order for the Silverlight UI to navigate to the next XAML page. It this delegate which carries out the event.

In the above example

    showResults r = new showResults(showResultsPage);

showResults is a delegate method which provides a reference to a method called showResultsPage which holds the code logic of navigating to the next XAML page.

    this.Dispatcher.BeginInvoke(r, new object[]
    {
     BingWebResults
    });

The Dispatcher object above gets the Threading.Dispatcher object this object is associated with. According to MSDN:

DispatcherObject can only be accessed by the Dispatcher it is associated with. For example, a background thread cannot update the contents of a Button that is associated with the Dispatcher on the UI thread. In order for the background thread to access the Content property of the Button, the background thread must delegate the work to the Dispatcher associated with the UI thread. This is accomplished by using either Invoke or BeginInvoke. **Invoke is synchronous and BeginInvoke is asynchronous**. The operation is added to the queue of the Dispatcher at the specified DispatcherPriority

If we did not use a delegate to change the UI of the Silverlight application in the middle of a asynchronous call the following Cross thread exception would be raised.

Last updated on 11 Sep 2009
Published on 11 Sep 2009