MOBILE

Windows Phone 7 Development : Using Rx.NET with Web Services to Asynchronously Retrieve Weather Data

4/23/2011 3:53:32 PM
In this section, you will use a publicly available weather web service located at www.webservicex.net/WCF/Default.aspx to retrieve and display current weather for a given zip code within the United States. In addition to weather services, there are many other useful web services available at this location, including zip code validation and currency conversion. As an exercise in the usage of Rx.NET, you are encouraged to build useful, functional applications that take advantage of these services.

From the development point of view, the weather application will consist of (1) asynchronously capturing user input—zip code, and (2) asynchronously calling the web service and then displaying the current weather for a given zip code. Let's go ahead and create the application.

1. Creating a Windows Phone Project

First, you will create a new project, import all of the libraries and create service references necessary to make the weather application work.

  1. Launch Visual Studio 2010 Express for Windows Phone and create a new Windows Phone Application project. Name it "WeatherRx."

  2. In MainPage.xaml, change the name of the application to "WeatherRx" and change the page title to "Weather App" (you are also certainly welcome to name the application and the page according to your preference).

  3. Since you will be using Rx.NET to build this application, add a reference (by right-clicking and selecting Add Reference) to Microsoft.Phone.Reactive and System.Observable assemblies.

You need to add a Service Reference to the weather service already mentioned. The weather service is an .asmx web service hosted at www.webservicex.net.

  1. To add a reference to this service, right-click the Project Name and select Add Service Reference. In the dialog that comes up, enter the following value in the Address Textbox: http://www.webservicex.net/WeatherForecast.asmx. Press the "Go" button.

  2. The WeatherForecast service should appear on the left. Click the arrow next to it, make sure to select WeatherForecastSoap service, and then rename the namespace to "svcWeather."

  3. Your final Add Service screen should look like Figure 1.

  4. Press the OK button.

    Figure 1. Adding a Service Reference to the weather web service

2. Creating a User Interface

For the application, your goal is to create a screen that looks like the one shown in Figure 2. To assist in that objective, the XAML for visual elements that appear after the page title is pasted here.

  1. Open MainPage.xaml and add the following code:

    <!--ContentPanel - place additional content here-->
    <Grid x:Name="ContentGrid" Grid.Row="1">
    <TextBox Height="72" HorizontalAlignment="Left" Margin="0,51,0,0"
    Name="txtZipCode" Text="" VerticalAlignment="Top" Width="480" />
    <TextBlock Height="53" HorizontalAlignment="Left" Margin="6,13,0,0"
    Name="lblLegend" Text="Enter Zip Code Below for Current Weather" VerticalAlignment="Top"
    Width="462" />
    <TextBlock Height="30" HorizontalAlignment="Left" Margin="6,129,0,0"


    Name="lblWeatherFahrenheit" Text="Current Weather, Fahrenheit " VerticalAlignment="Top"
    Width="435" />
    <Image Height="150" HorizontalAlignment="Left" Margin="241,213,0,0"
    Name="imgWeather" Stretch="Fill" VerticalAlignment="Top" Width="200" />
    <TextBlock Height="30" HorizontalAlignment="Left" Margin="6,162,0,0"
    Name="lblCelsius" Text="Current Weather, Celsius" VerticalAlignment="Top" Width="435" />
    <TextBlock Height="30" Margin="6,379,39,0" Name="lblStatus" Text="" VerticalAlignment="Top" />
    </Grid>
    </Grid>


Notice that in addition to the textblocks that will hold the current weather information, the XAML also creates an image control that will show a visual representation of the current weather (e.g., sunny, raining, snowing, etc.). Notice also that the last </Grid>statement closes the LayoutGrid element, not shown in the preceding fragment.

Figure 2. WeatherRx design layout

3. Adding Logic to Get Weather Information

With design elements and proper references in place, you are ready to add code to the application. In this walkthrough, you will split the code into multiple functions for enhanced readability.

  1. Open MainPage.xaml.cs (by clicking MainPage.xaml and selecting View Code) and add the following using statements to the top of the page:

    using Microsoft.Phone.Reactive;
    using System.Windows.Media.Imaging;

  2. Add the following code after the InitializeComponent() statement of the MainPage() constructor:

    WireUpWeatherEvents();
    WireUpKeyEvents();

  1. Create the WireUpWeatherEvents function and its supporting GetWeatherSubject function by pasting the following code. Note how you have created a separate function (GetWeatherSubject) to return an Observable collection from the weather web service event.

    private void WireUpWeatherEvents()
    {
    var weather = GetWeatherSubject();
    weather.ObserveOn(Deployment.Current.Dispatcher).Subscribe(evt =>
    {

    if (evt.EventArgs.Result.Details != null)
    {
    lblWeatherFahrenheit.Text = "Current Weather, Fahrenheit: " +
    evt.EventArgs.Result.Details[0].MinTemperatureF.ToString() + " - " +
    evt.EventArgs.Result.Details[0].MaxTemperatureF.ToString();
    lblCelsius.Text = "Current Weather, Celsius: " +
    evt.EventArgs.Result.Details[0].MinTemperatureC.ToString() + " - " +
    evt.EventArgs.Result.Details[0].MaxTemperatureC.ToString();
    imgWeather.Source = new BitmapImage(new
    Uri(evt.EventArgs.Result.Details[0].WeatherImage, UriKind.Absolute));
    }
    },
    ex => { lblStatus.Text = "Sorry, we encountered a problem: " + ex.Message; }
    );
    }

    private IObservable<IEvent<svcWeather.GetWeatherByZipCodeCompletedEventArgs>>
    GetWeatherSubject()
    {
    var weather = Observable.FromEvent<svcWeather.GetWeatherByZipCodeCompletedEventArgs>(weatherClient,
    "GetWeatherByZipCodeCompleted");
    return weather;
    }


  2. Create the WireUpKeyEvents function that will create an Observable collection from the KeyUp events and create subscription to that collection by adding the following code:

    private void WireUpKeyEvents()
    {
    var keys = Observable.FromEvent<KeyEventArgs>(txtZipCode,
    "KeyUp").Throttle(TimeSpan.FromSeconds(1)).DistinctUntilChanged();
    keys.ObserveOn(Deployment.Current.Dispatcher).Subscribe(evt =>
    {
    if (txtZipCode.Text.Length >= 5)
    {
    weatherClient.GetWeatherByZipCodeAsync(txtZipCode.Text);
    }
    });

    }


  3. Press F5 to run the application. You should see a screen prompting you to enter the US zip code to retrieve the current weather for. If you enter your zip code, you should get a reasonable estimate of your current weather, both on the Fahrenheit and Celsius scales. You should also see a small picture with a visual representation of the current weather conditions. Figure 4 shows sample output for the Jacksonville, FL area (zip code of "32202").

Let's spend some more time dissecting the tools you used to build this application. First, you used Rx.NET to create an Observable collection from the asynchronous responses to the weather web service calls. You used the following statement to create that collection:

var weather =
Observable.FromEvent<svcWeather.GetWeatherByZipCodeCompletedEventArgs>(weatherClient,
"GetWeatherByZipCodeCompleted");


You then defined an Observer for this data source, so that when the data is pushed from the web service to Observers, you take action by displaying that data in the User Interface.

Next, you created an Observable collection of the KeyUp events in the txtZipCode text box and created an Observer for that collection. As a result, whenever users pause their typing for one second, the Observer on the keys data source will validate whether five or more digits have been entered in the Zip Code field. Then, it goes ahead and calls the function GetWeatherByZipCodeAsync, which in turn invokes an asynchronous request to the weather web service.

It's important to note the asynchronous nature of all these calls—if you had other functionality built into the application, you could continue using it while the asynchronous request completes. The asynchronous processing is an area that Rx.NET was specifically designed to address.

If you have done some form of asynchronous programming prior to Rx.NET, you can certainly appreciate that foregoing single code line. Prior to Rx.NET, in an asynchronous method design pattern in .NET, two methods were provided. The first method started the computation, and the second method acquired the results of the computation. If there was more than one asynchronous operation, even just the simple ones we have illustrated in the weather example, the management of those multiple methods quickly became a headache. The fact that Rx.NET also attempts to parallelize asynchronous requests across all available cores is a hefty bonus to an already generous benefits package of clarity and powerful querying of Observers.

Figure 4. Sample output of WeatherRx application for zip code 32202

Other  
  •  Windows Phone 7 Development : Media - Adding Sounds to an Application
  •  iPhone Application Development : Building a Multi-View Tab Bar Application (part 4) - Implementing the Summary View
  •  iPhone Application Development : Building a Multi-View Tab Bar Application (part 3) - Implementing the Volume View
  •  iPhone Application Development : Building a Multi-View Tab Bar Application (part 2) - Implementing the Area View
  •  iPhone Application Development : Building a Multi-View Tab Bar Application (part 1)
  •  Windows Phone 7 Development : Working with Video (part 2) - Coding the Application
  •  Windows Phone 7 Development : Working with Video (part 1)
  •  Windows Phone 7 Development : Plotting an Address on a Bing Maps Map and Working with the Bing Maps Service
  •  Windows Phone 7 Development : Using GeoCoordinateWatcher and the Bing Maps Control to Track Your Movements
  •  iPhone Application Development : Creating a Multi-View Toolbar Application (part 3) - Adding Toolbar Controls
  •  iPhone Application Development : Creating a Multi-View Toolbar Application (part 2) - Instantiating the View Controllers
  •  iPhone Application Development : Creating a Multi-View Toolbar Application (part 1)
  •  Windows Phone 7 Development : Using Location Services - Simulating the Location Service
  •  Introducing the Windows Phone Location Service and Mapping APIs
  •  iPhone Application Development : Implementing a Custom Picker View (part 4) - Tweaking the Picker UI
  •  iPhone Application Development : Implementing a Custom Picker View (part 3) - Reacting to a Picker View Choice
  •  iPhone Application Development : Implementing a Custom Picker View (part 2)
  •  iPhone Application Development : Implementing a Custom Picker View (part 1)
  •  Windows Phone 7 Development : Isolated Storage - Working with Isolated Storage Settings
  •  Mobile Application Security : WebOS Security - Permissions and User Controls
  •  
    Most View
    Evga GTX 690 - Hail To The King
    Tech Preview 2013 (Part 1) - Next-Gen Gpus
    Record Onscreen Action In Windows
    Open GL : Storing Transformed Vertices—Transform Feedback (part 1)
    SilverStone Sugo SG08 - A Tiny Case With Great Cooling
    SAM PowerPC With AmigaOS 4.1
    Go Baby Mobile Dongle Dock
    Fujifilm X-S1: Master of... all
    iPhone 3D Programming : Textures and Image Capture - Texture Formats and Types
    Pioneer Has Launched 3 Speakers Supporting AirPlay And DLNA
    Top 10
    ADO.NET Programming : Microsoft SQL Server (part 4) - Working with Typed Data Sets
    ADO.NET Programming : Microsoft SQL Server (part 3) - Using Stored Procedures with DataSet Objects
    ADO.NET Programming : Microsoft SQL Server (part 2) - Using SQL Server Stored Procedures
    ADO.NET Programming : Microsoft SQL Server (part 1) - Connecting to SQL Server, Creating Command Objects
    Windows Phone 8 In-Depth Review (Part 6)
    Windows Phone 8 In-Depth Review (Part 5)
    Windows Phone 8 In-Depth Review (Part 4)
    Windows Phone 8 In-Depth Review (Part 3)
    Windows Phone 8 In-Depth Review (Part 2)
    Windows Phone 8 In-Depth Review (Part 1)