Accessing a REST Web Service
Silverlight quickstart for Windows Phone development
Representational State Transfer (REST) refers to an architectural style for exposing resources on the web for access by clients. Many resources, such as blogs, maps, and products, are exposed as REST services on the web. Silverlight provides classes that make it easy to call REST services from a Windows Phone application. This QuickStart introduces how to call and work with REST services.
This QuickStart contains the following sections:
Note
The live samples in this QuickStart use Silverlight running in the browser to simulate the behavior in Silverlight for Windows Phone. The actual behavior may be slightly different in the Windows Phone emulator or on a Windows Phone device.
Calling REST Services
You call a REST service by using standard HTTP verbs (GET, POST, PUT, and DELETE). Resources are identified by a URI. A response contains a representation, typically XML or JavaScript Object Notation (JSON), of the specified resource. Requests are stateless, which means that all the information needed to complete a request must be included with each request.
One important aspect of calling a REST service is ensuring that you use the correct URI for the resource you' trying to access. Companies typically list the request requirements, including request parameters and the values that you should pass for the parameters. For example, to call the Bing Web services, you can review the Bing API guidelines.
Silverlight for Windows Phone provides several classes to call REST services. It's important to remember, however, that Windows Phone supports Silverlight 3, which means Silverlight 4 networking features aren't available to Windows Phone clients. For more information about the differences in networking capability between Silverlight for Windows Phone and Silverlight for the desktop, see Networking in Silverlight for Windows Phone.
To call a REST service from a Windows Phone client application, you can use either the WebClient or HttpWebRequest/HttpWebResponse classes. With either option, the requests are asynchronous. However, WebClient is the simpler of the two choices.
WebClient uses a simple event-based system to make requests and retrieve responses. To use WebClient, you call the appropriate Async method and handle the corresponding Completed event. The following table lists some of the WebClient methods and events that you should use, depending on the action and data type.
The HttpWebRequest class enables you to have more control over the request message, such as sending HTTP PUT and DELETE messages. For more information about using the HttpWebRequest/HttpWebResponse classes, see the HttpWebRequest class overview.
Calling a REST Service Example
The following live example demonstrates how to use the WebClient class to send a request from a phone application to the Bing search service. In this example, you can change the selected search term by using the combo box, which updates the search URI. When you click the Search! button, a request is sent to the Bing search service. In addition to the search term, the request URI specifies that the results are a Web search and that the response is in XML. The results are parsed and displayed in the list box.
Note
Although the live example includes a Bing Application ID in the URI to complete the search request, the actual Application ID isn't shown in the code. To obtain an Application ID to call the Bing search service, see Getting Started with Bing Api Version 2.
Security Note
When connecting to a web service that requires an application key, don't store the application key with an application that will be run on a device. Instead, you can create a proxy web service to authenticate a user and call an external cloud service with the application key. For more information about security recommendations, see Web Service Security for Windows Phone.
The following shows the markup and code for this example.
XAML
<phone:PhoneApplicationPage
x:Class="WindowsPhoneApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="False">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.Resources>
<Style x:Key="ComboBoxItemStyle" TargetType="ComboBoxItem" >
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="LightGray"/>
</Style>
<Style x:Key="ComboBoxStyle" TargetType="ComboBox" >
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="Gray"/>
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="REST CLIENT"
Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="bing search"
Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"
Height="99" Width="453" />
</StackPanel>
<Grid x:Name="ContentPanel" Margin="12,139,12,0" Grid.RowSpan="2">
<Button Content="Search!" Height="89" HorizontalAlignment="Left"
Margin="264,140,0,0" Name="button1"
VerticalAlignment="Top" Width="189" Click="button1_Click" />
<ComboBox Height="50" Style="{StaticResource ComboBoxStyle}"
HorizontalAlignment="Left" Margin="6,159" Name="comboBox1"
ItemContainerStyle="{StaticResource ComboBoxItemStyle}"
VerticalAlignment="Top" Width="235" ItemsSource="{Binding}"
SelectionChanged="comboBox1_SelectionChanged" />
<TextBlock Height="36" HorizontalAlignment="Left" Margin="12,120"
Name="textBlock2" Text="Search Topic:" VerticalAlignment="Top" Width="121" />
<TextBlock Height="23" HorizontalAlignment="Left" Margin="12,1,0,0"
Name="textBlock3"
Text="URI:" VerticalAlignment="Top" />
<TextBlock Height="86" HorizontalAlignment="Left" Margin="6,28"
Name="uriTextBlock" TextWrapping="Wrap" Text="{Binding}"
VerticalAlignment="Top" Width="447" />
<TextBlock Height="23" HorizontalAlignment="Left" Margin="12,242,0,0"
Name="textBlock5"
Text="Results:" VerticalAlignment="Top" />
<ListBox Height="352" HorizontalAlignment="Left" Margin="6,271,0,0" Name="listBox1"
VerticalAlignment="Top" Width="444" ItemsSource="{Binding}" >
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="{StaticResource PhoneForegroundBrush}" Width="418" BorderThickness="2"
Margin="2">
<StackPanel>
<TextBlock Text="{Binding Path=Title}" TextWrapping="Wrap" />
<TextBlock Text="{Binding Path=Url}" TextWrapping="Wrap"/>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Xml.Linq;
namespace WindowsPhoneApplication1
{
public partial class MainPage : PhoneApplicationPage
{
String requestString =
"http://api.bing.net/xml.aspx?AppId='YourAppId'&Query={0}&Sources=Web&Version=2.0&Market=en-us&Adult=Strict";
string UriNoAppId =
"http://api.bing.net/xml.aspx?AppId='YourAppId'&Query={0}&Sources=Web&Version=2.0&Market=en-us&Adult=Strict";
public MainPage()
{
InitializeComponent();
List<string> searchTopics = new List<string>() { "Microsoft", "Silverlight", "Windows Phone" };
comboBox1.DataContext = searchTopics;
comboBox1.SelectedIndex = 0;
wc = new WebClient();
wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
}
WebClient wc;
private void CallToWebService()
{
wc.OpenReadAsync(new Uri(String.Format(requestString, comboBox1.SelectedItem.ToString())));
}
void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
XElement resultXml;
if (e.Error != null)
{
return;
}
else
{
XNamespace web = "http://schemas.microsoft.com/LiveSearch/2008/04/XML/web";
try
{
resultXml = XElement.Load(e.Result);
var searchResults =
from result in resultXml.Descendants(web + "WebResult")
select new SearchResult
{
Title = result.Element(web + "Title").Value,
Description = result.Element(web + "Description").Value,
Url = result.Element(web + "Url").Value
};
listBox1.DataContext = searchResults;
}
catch (System.Xml.XmlException ex)
{
textBlock2.Text = ex.Message;
}
}
}
private void button1_Click(object sender, RoutedEventArgs e)
{
CallToWebService();
}
private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
uriTextBlock.DataContext = string.Format(UriNoAppId, e.AddedItems[0]);
}
}
public class SearchResult
{
public string Title { get; set; }
public string Url { get; set; }
public string Description { get; set; }
}
}
Visual Basic
Imports System.Collections.Generic
Imports System.Linq
Imports System.Net
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Documents
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Shapes
Imports Microsoft.Phone.Controls
Imports System.Xml.Linq
Namespace WindowsPhoneApplication1
Public Partial Class MainPage
Inherits PhoneApplicationPage
Private requestString As [String] = "http://api.bing.net/xml.aspx?AppId='YourAppId'&Query={0}&Sources=Web&Version=2.0&Market=en-us&Adult=Strict"
Private UriNoAppId As String = "http://api.bing.net/xml.aspx?AppId='YourAppId'&Query={0}&Sources=Web&Version=2.0&Market=en-us&Adult=Strict"
Public Sub New()
InitializeComponent()
Dim searchTopics As New List(Of String)() From { _
"Microsoft", _
"Silverlight", _
"Windows Phone" _
}
comboBox1.DataContext = searchTopics
comboBox1.SelectedIndex = 0
' Create the WebClient and associate a handler with the OpenReadCompleted event.
wc = New WebClient()
AddHandler wc.OpenReadCompleted, New OpenReadCompletedEventHandler(AddressOf wc_OpenReadCompleted)
End Sub
' Call the topic service at the Bing search site.
Private wc As WebClient
Private Sub CallToWebService()
wc.OpenReadAsync(New Uri([String].Format(requestString, comboBox1.SelectedItem.ToString())))
End Sub
Private Sub wc_OpenReadCompleted(sender As Object, e As OpenReadCompletedEventArgs)
Dim resultXml As XElement
If e.[Error] IsNot Nothing Then
Return
Else
Dim web As XNamespace = "http://schemas.microsoft.com/LiveSearch/2008/04/XML/web"
Try
resultXml = XElement.Load(e.Result)
Dim searchResults = From result In resultXml.Descendants(web & "WebResult")New SearchResult() With { _
Key .Title = result.Element(web & "Title").Value, _
Key .Description = result.Element(web & "Description").Value, _
Key .Url = result.Element(web & "Url").Value _
}
' Set the data context for the listbox to the results.
listBox1.DataContext = searchResults
Catch ex As System.Xml.XmlException
textBlock2.Text = ex.Message
End Try
End If
End Sub
Private Sub button1_Click(sender As Object, e As RoutedEventArgs)
CallToWebService()
End Sub
' Update the textblock as the combo box selection changes.
Private Sub comboBox1_SelectionChanged(sender As Object, e As SelectionChangedEventArgs)
uriTextBlock.DataContext = String.Format(UriNoAppId, e.AddedItems(0))
End Sub
End Class
' Simple class to hold the search results.
Public Class SearchResult
Public Property Title() As String
Get
Return m_Title
End Get
Set
m_Title = Value
End Set
End Property
Private m_Title As String
Public Property Url() As String
Get
Return m_Url
End Get
Set
m_Url = Value
End Set
End Property
Private m_Url As String
Public Property Description() As String
Get
Return m_Description
End Get
Set
m_Description = Value
End Set
End Property
Private m_Description As String
End Class
End Namespace
Detecting Networking Availability
To ensure a good user experience, you should verify that the phone has access to the Internet before calling a web service. You use the NetworkInterface.GetIsNetworkAvailable method to determine whether the phone has Internet connectivity. You can call this method before calling the web service. If the method returns false, either prompt the user to connect to a viable network, or let the user know that the web service call can't be completed. For an example of how to use this method, see the NetworkInterface.GetIsNetworkAvailable reference topic.
See Also