(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

Using RESTful services from Silverlight

(9 votes)
Gill Cleeren
>
Gill Cleeren
Joined Apr 02, 2010
Articles:   63
Comments:   6
More Articles
9 comments   /   posted on Nov 22, 2010
Tags:   rest , restful , wcf , ado.net , gill-cleeren
Categories:   Data Access , General

This article is compatible with the latest version of Silverlight.

Introduction

For its data needs, Silverlight needs to connect to a service. Since Silverlight is a client-side technology, services are the way for Silverlight to get to data that resides on the server. In the current release, there is no support for any ADO.NET related functionality (so no DataReaders, DataSets and no LINQ-To-SQL). That means we can’t connect from Silverlight to a database available on some server by simple using a connection string and creating a connection from the Silverlight client. If we do want access to that data, we need to place a service in front of the database (that in most cases will call a business layer that in turn will call a data access layer that in its turn will access the database).

Luckily, Silverlight 4 is very rich in the number and types of services it can work with. Silverlight can easily connect with WCF/ASMX services. These services are said to be self-describing, as they expose a WDSL endpoint that we can connect to. A WSDL endpoint exposes all the information about the service (supported methods, supported data types) and is used by Visual Studio to create a client-side proxy. This proxy can then be instantiated in our Silverlight code to communicate with the actual service. This type of service communication sends the data using SOAP. SOAP is a messaging format that is XML, however, the data is wrapped in a SOAP envelope. This can be seen as an overhead, since quite a lot of extra information is sent for each message on top of the actual data. On the other hand, using WCF gives us the most options in Silverlight, including duplex messaging, debugging of services etc.

Thinking back of the mentioned overhead: in some situations, we don’t always need all the features offered us by WCF. In some cases, we only need to send or receive pure textual information, mostly in XML format. We may not need all the extra features added when exchanging our data in SOAP format. In this situation, another protocol is supported in Silverlight called REST (REpresentational State Transfer). REST is becoming a very popular format to use: many large web applications (I call them applications, since they are more than merely a web site) such as Facebook, Twitter and YouTube offer (part of) their functionality for us to use in our applications as REST services (forming a REST API).

In this article, we are going to take a look at what options we have to connect to REST services from our applications. For this article, we’ll use a REST service that we create ourselves first. The service is a sample weather service that can return and update some weather information. This type of service is a good candidate for a REST service: there’s no data going over the line that needs to be secured (weather information can hardly be called sensitive data…) and since this is general purpose service, many third party systems may wish to connect to our service. Since REST is based on standards, it can easily be used from any technology. The UI of the application can be seen here:

The source code for this article can be downloaded here.

Don’t worry, take some REST

As said, REST is a protocol that uses plain text to exchange information. The information is mostly in XML or JSON. As most of the sent data is “actual data”, there’s less overhead than when using WCF. One of the basic principles of REST is that all data should be addressable using a URL. This data is then considered a resource. The WWW can be seen as a large REST implementation: each resource (a page in this case) has a unique URL that can be used to access it.

Another advantage of REST is that it is platform independent, since it uses basic HTTP verbs (such as GET). This results in the fact that a REST service written in any technology can be used by Silverlight. Using WCF, it’s actually very easy to create a REST service, as we’ll see in this article. Services that communicate over REST are said to be RESTful services.

Silverlight wants some REST

OK, I’m done with the REST jokes. Let’s take a look at what we need to do to connect to our own written REST service.

Creating the REST service

To connect to a self-written REST service, the first step is of course, authoring it. Using WCF, this is actually very easy. In the sample, there are 2 services that return data: the first one returns the forecasted weather for tomorrow, the second one returns a five day forecast.

To write a REST service, start by adding a Silverlight-enabled WCF service. In this case, the service is called WeatherService.svc. At this point, this is a “normal” WCF service. To make the operations work over a REST call, add the WebGet attribute on the operation. The UriTemplate specifies the address of the method within the service: for example, if our service is WeatherService.svc and the UriTemplate is set to “tomorrow”, the method can be called using WeatherService.svc/tomorrow. Furthermore, the RequestFormat specifies that this service will return information over XML here (JSON is the second option).

[OperationContract]
[WebGet(UriTemplate = "tomorrow", BodyStyle = WebMessageBodyStyle.Bare, 
    RequestFormat = WebMessageFormat.Xml)]
public DayWeather TomorrowWeather()
{
    //Mocking this data here
    return WeatherRepository.TomorrowWeather;
}

To get it working, we also need to perform some configuration changes. In the Web.config, the following changes need to be done:

  • Add the webHttp behavior to the endpoint behaviors:
    <behaviors>
        ...
      <endpointBehaviors>
        <behavior name="webBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
  • Make sure this behavior is used for your service:
    <service name="RESTWeather.Web.WeatherService">
        <endpoint address="" behaviorConfiguration="webBehavior" 
            binding="webHttpBinding" contract="RESTWeather.Web.WeatherService" />
        <endpoint address="rest" behaviorConfiguration="webBehavior" 
            binding="webHttpBinding" contract="RESTWeather.Web.WeatherService" />
    </service>

We can now test this service using the following URL:
http://localhost:6568/WeatherService.svc/tomorrow

The response is as expected XML:

<DayWeather xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <DayTemperature>-3</DayTemperature>
  <Forecast>Snow</Forecast>
  <NightTemperature>-8</NightTemperature>
</DayWeather>

From our Silverlight application, we can now make a call to this REST service.

Connecting and reading from the REST service

Because a REST service does not have an endpoint to which we can create a service reference, we need another way of communicating with it. The easiest, and in most situations, best solution is using the WebClient class (alternatively, the HttpWebRequest can be used). This class, which lives in the System.Net namespace also exist in the regular .NET framework and can be used to send a request to a URL and capture the response.

Communicating with a REST service (and for that matter, any POX (Plain Old Xml) service), requires us to follow these 3 steps:

  • Create the URL to which we need to connect
  • Send a request to this URL
  • Capture and parse the result (in our case, XML)

In the sample, the URL is hardcoded:

private string baseUrl = "http://localhost:6568/WeatherService.svc/";
private string tomorrowForecastUrlSuffix = "tomorrow";

When the user now clicks on the Tomorrow HyperlinkButton, the following code is executed:

private void TomorrowLink_Click(object sender, RoutedEventArgs e)
{
    //build up URL
    string tomorrowForecastUrl = baseUrl + tomorrowForecastUrlSuffix;
 
    GetWeatherFromRestService(tomorrowForecastUrl);
}
 
private void GetWeatherFromRestService(string tomorrowForecastUrl)
{
    WebClient client = new WebClient();
    client.DownloadStringCompleted += (s, ev) =>
    {
        XDocument xml = XDocument.Parse(ev.Result);
 
        var weather = from results in xml.Descendants("DayWeather")
                      select new DayWeather
                      {
                          Forecast = results.Element("Forecast").Value.ToString(),
                          DayTemperature = Int32.Parse(results.Descendants("DayTemperature").First().Value),
                          NightTemperature = Int32.Parse(results.Descendants("NightTemperature").First().Value),
                      };
 
        ObservableCollection<DayWeather> dayWeatherList = new ObservableCollection<DayWeather>(weather.ToList());
        ForecastListBox.ItemsSource = dayWeatherList;
    };
    client.DownloadStringAsync(new Uri(tomorrowForecastUrl));
}

This code executes the above mentioned steps. It uses the URL of the REST service. Then, it sends a request to this service URL using the WebClient class. As with all other communication, this call happens asynchronously. Using the DownloadStringAsync, we perform the actual call; in the callback, we get in the e.Result parameter the XML as it was retrieved from the service. We are responsible ourselves for the parsing of this XML, this is in contrast to using a WCF/ASMX service where this is done for us.

We use Linq-To-XML here, as it is the easiest way to parse XML. Silverlight has other options on board though, including the traditional XmlReader. The Five Day Forecast is similar and can be found in the sample code.

Now that we know how to read from a REST service, can we also use it to save data back to the server?

Saving data using REST

A REST service is capable of accepting data. Remember that we mentioned that REST uses standard HTTP methods? Well, we can use exactly that to perform saving of data. Let’s first create a service method for this as follows:

[OperationContract]
[WebInvoke(UriTemplate = "tomorrow/update", Method = "POST", RequestFormat = WebMessageFormat.Xml)]
public void UpdateTomorrowWeather(DayWeather newWeather)
{
    WeatherRepository.TomorrowWeather = newWeather;
}

Note that the Method parameter is now set to POST, indicating that our client can using the standard HTTP Post method send data to the service.

In the Silverlight client, we can now use this method to perform a save operation over REST. In the code below, we are doing exactly that, again based on the WebClient. We however need to perform some more work ourselves. We need to serialize the data we want to send into an XML string. Also, the headers need to be set on the request to XML. Finally, we need to use the UploadStringAsync method of the WebClient to upload the XML to the REST service, specifying that we want to do a POST.

WebClient client = new WebClient();
 
string updateWeatherUri = baseUrl + updateTomorrowSuffix;
 
DataContractSerializer dataContractSerializer = 
    new DataContractSerializer(typeof(DayWeather));
MemoryStream memoryStream = new MemoryStream();
dataContractSerializer.WriteObject(memoryStream, _dayWeather);
string xmlData = Encoding.UTF8.GetString(memoryStream.ToArray(), 0, (int)memoryStream.Length);
 
client.UploadStringCompleted += (s, ev) =>
{
    if (ev.Error == null)
    this.DialogResult = true;
};
client.Headers[HttpRequestHeader.ContentType] = "application/xml";
client.UploadStringAsync(new Uri(updateWeatherUri), "POST", xmlData);

Conclusion

The REST protocol is popular and that’s easy to understand. It’s supported on most technologies and of course, Silverlight is one of them. REST services can be used from Silverlight to perform read and save operations. A bit more work is required though, since there’s no automatic serialization happening because of the lack of a WSDL file within the REST service.

About the author

Gill Cleeren is Microsoft Regional Director (www.theregion.com), MVP ASP.NET, INETA speaker bureau member and Silverlight Insider. He lives in Belgium where he works as .NET architect at Ordina. Passionate about .NET, he’s always playing with the newest bits. In his role as Regional Director, Gill has given many sessions, webcasts and trainings on new as well as existing technologies, such as Silverlight, ASP.NET and WPF. He also leads Visug (www.visug.be), the largest .NET user group in Belgium. He’s also the author of “Silverlight 4 Data and Serivices Cookbook”, published by Packt Publishing. You can find his blog at www.snowball.be.


Subscribe

Comments

  • Calabonga

    RE: Using RESTful services from Silverlight


    posted by Calabonga on Nov 23, 2010 07:34
    This post was very helpful, thanks!
  • -_-

    RE: Using RESTful services from Silverlight


    posted by Akshya Kumar Panda on Mar 15, 2011 15:38
    It s a nice piece of code that give idea about the RESTFull services.Doing good work and thanks for this work
  • -_-

    RE: Using RESTful services from Silverlight


    posted by Hemant on Apr 20, 2011 09:35
    iam not able to get DayWhether class in silverlight project.
  • -_-

    RE: Using RESTful services from Silverlight


    posted by Gill Cleeren on Apr 20, 2011 10:53
    @Hemant: what do you mean that you can't get the class in the project?
  • suede

    Re: Using RESTful services from Silverlight


    posted by suede on Oct 04, 2011 17:57

    Gill,

    I am stumbling over the same issue as Hemant. In order for you to consume the Dayweather Object in the silverlight client, you must have a reference to it somehow or perhaps duplicate the business objects on the client....which imo is not practical. Any help would be great ty.:) 

  • suede

    Re: Using RESTful services from Silverlight


    posted by suede on Oct 04, 2011 18:00

    oh and by the way, I am using the WCF service application as the initial template for the REST service.

  • arti-singh

    Re: Using RESTful services from Silverlight


    posted by arti-singh on Jun 04, 2012 13:03

     

    Please guide me how to pass a user defined object to rest service for save or update operation--(i had tried both webclient as well as httpwebRequest ,but i am getting same error from both)

    with reference to the above code, i had written the code for passing my user defined object to rest service for save operation ,but i am getting error remote server returned an error: not found in client.UploadStringCompleted event handler.

    I am able to get my object same as above code, get part is executting successfully & i am getting my object but when i tried to pass object  in post method i am getting the error, My code snippt is as per below--

           //This is the method in rest service--

            [WebInvoke(UriTemplate = "CreateNewEmployee",

             Method = "POST",RequestFormat=WebMessageFormat.Xml,

            ResponseFormat =     WebMessageFormat.Xml)]

        public string PostEmployeeDetail(EmployeeDetail objEmployee)

    {

        //Some code is here

    }

        

    // below is the method written in silverlight 4.0 client

      

     

            private void SaveEmployeeList()

            {

             

                WebClient client = new WebClient();

                string updateUri = @"http://localhost:54475/Service1/CreateNewEmployee/";

     

                EmployeeDetail objNewEmployee = new EmployeeDetail();

                objNewEmployee.EmployeeIdentifier = 1;

                objNewEmployee.EmployeeName = "Arti Singh";

                objNewEmployee.ProjectName = "SmartGrid";

     

                DataContractSerializer dataContractSerializer = new DataContractSerializer(typeof(EmployeeDetail));

                MemoryStream memoryStream = new MemoryStream();

                dataContractSerializer.WriteObject(memoryStream, objNewEmployee);

                string xmlData = (System.Text.Encoding.UTF8.GetString(memoryStream.ToArray(), 0, (int)memoryStream.Length));

     

                client.UploadStringCompleted += new UploadStringCompletedEventHandler (client_UploadStringCompleted);

                client.Headers[HttpRequestHeader.ContentType] = "application/xml";

                client.Encoding = System.Text.Encoding.UTF8;

                client.UploadStringAsync(new Uri(updateUri), "POST", xmlData);

     

            }

     

     

     

               void client_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)

            { 

                if (e.Error == null)

                    MessageBox.Show(e.Result);

            }

     

    i stucked over here & could not get any solution for it..

  • venkat.ravi231

    Re: Using RESTful services from Silverlight


    posted by venkat.ravi231 on Sep 11, 2012 09:30

    Hi All,

    I am getting an error at line "XDocument xml = XDocument.Parse(e.Result);"

    An exception occurred during the operation, making the result invalid.  Check InnerException for exception details.

    Could anyone please help me? I am new to this technology and in the beginning stage.

    Thanks,

    Venkat.


  • nixon

    Re: Using RESTful services from Silverlight


    posted by nixon on Feb 25, 2013 15:30

    Hi Gill

    i read your article ,its simple and good for beginners.can u explain put and delete method in your article .i can't find anywhere  example like this.there is only 1 0r 2 articles explain how to  consume rest service in silverlight .so its great help for beginners like me..

    Advance Thanks

    Nixon

Add Comment

Login to comment:
  *      *