Azure Application Part 3: Expose (REST) Web Service And Consume in Silverlight
This is part 3 in this series where I am building an Azure shopping cart application from the ground up. In this post, I will create a RESTful service using WCF and host it in Windows Azure. This service will source it’s data from Azure Table Storage. I will then illustrate how to consume this service from a Silverlight component hosted in Windows Azure. Giddyup.
(In part 2 I illustrated how to set up and access Azure Table Storage in both the development environment, as well as in the cloud. I created a Wine table, added a few entities and retrieved them both locally and from the cloud. I did all this taking advantage of the ADO.NET Data Services .NET Client Library and the StorageClient sample application.)
Watch the Screencast
Building Our RESTful Service
By now, you have more than likely heard of REST and have at least an ancillary understanding of it. I further hope you have had the chance to develop RESTful services, taking advantage of our webHttpBinding in WCF. If not, I invite you to look at my 10 part series on REST in WCF. In that series, I provide an overview of REST and illustrate how to implement RESTful services using WCF 3.5. The goal of this post is not to do a deep dive on REST, rather, to illustrate that you can host these WCF RESTful services in Windows Azure (as well as consume them from components hosted in and out of Windows Azure). That being said, if you are not familiar, I will provide a 50,000 foot description of what REST is. (please forgive me, but I am copying this description almost verbatim from an earlier post of mine)
REST is an architectural style that embraces the standards of the web such as HTTP and URI. Because it is an “architectural style” there are endless debates as to what is RESTful and just what REST means. I only intend to provide a general overview of REST here, as addressing that debate is beyond the scope of this post. However, if you are interested in an in-depth understanding of REST, please read/view my 10+ part series of posts and screencasts on the subject.
In general, exposing services using a RESTful architectural style simply means embracing and adhering to the standards of the web. What the heck does that mean? Here are some examples:
- Treat everything as a resource and use URIs to uniquely identify resources. My customers may be represented as http://www.robbagby.com/customers, whereas a single customer named fred may be represented as http://www.robbagby.com/customers/fred. Finally my customers that have not paid may be represented as http://www.robbagby.com/deadbeatcustomers.
- Use the appropriate HTTP Verbs (GET, PUT, POST, DELETE) for the appropriate action. Issue an HTTP GET to http://www.robbagby.com/customers/fred fetch a representation of fred, whereas issue an HTTP DELETE to the same URI to perform a delete action.
- Where appropriate, use standard representation formats (ATOM, XHTML, Microformats, etc.) to represent resources.
- Use HTTP Headers appropriately
- Use HTTP Status Codes to alert the caller as to the result of the call.
- The Accept HTTP Header can be used to alert the server to the representation format you would prefer.
- Use the Authorization header for authorization credentials.
The above list is certainly not an exhaustive list, but should give you a general idea of what REST is (with regards to services).
Why Build a RESTful Service
For the purposes of this post, we are going to create a simple GET service that simply exposes the Wines that we are storing in Azure Table Storage. Why are we going to do that? Azure Table Storage data is already exposed RESTfully, isn’t it? Well there are a few reasons. They are as follows:
- Perhaps we want to expose our wines without requiring authentication.
- Perhaps we want to expose our wines in a different representation format than ATOM (such as JSON or POX or whatever we feel like)
- Perhaps we want to massage the data prior to exposing it.
- Perhaps this data was not sourced in Azure Table Storage. Perhaps this data was stored in SDS.
- We want to consume this data from Silverlight. Silverlight precluded you from adding an Authentication header when making a request. Therefore, as of now, you cannot directly access Azure Table Storage via Silverlight.
- This is a sample, so I want to keep this part simple. I do not want to overcomplicate the sample with a bunch of data manipulation.
- Implement Our RESTful Service
There are many ways to skin a cat (I just learned last night that this saying has nothing to do with felines, rather Catfish – go figure). What I mean is that there are multiple ways to create a REST service with WCF. There are 2 out-of-the-box templates and a bunch more in the WCF REST Starter Kit on CodePlex. I am going to use the AJAX template (and de-AJAXify it) because it take a few steps and renders very clean code. For production applications, I would strongly urge you to take a look at the WCF REST Starter Kit. Enough babbling, here are the steps to create the service:
- Right-Click on the AzureStore_WebRole project > Add > New Item
- Choose the ‘AJAX-enabled WCF Service template and Name it: WineService.svc
- The template did a few things for us:
- It added references for us, including System.ServiceModel
- It added a System.ServiceModel element in the web.config (if there wasn’t on, which in our example there wasn’t). Under this node, it added the appropriate WCF Configurations, including an endpoint with our RESTful binding webHttpBinding and a pointer to an enableWebScript endpoint behavior (the AJAXiness of this template).
- It added an svc file. This file acts as the endpoint when hosting in IIS or WAS. The file has a ServiceHost directive, pointing to the type that contains the service code, among other things as we’ll see in a minute
- It added a class file that contains the implementation. The ServiceHost above points both to the physical location of this class (CodeBehind), as well as the type (Service). This class is where we are going to do our work.
- Open the web.config and delete the System.ServiceModel section of the configuration (from <System.ServiceModel>… to </System.ServiceModel>). This template used a configuration approach. We are going to go with a configurationless model. We do this by declaring a Factory in the ServiceHost directive in the svc file.
- Open up the svc file (right-click on the svc file > View Markup).
- Add Factory=”System.ServiceModel.Activation.WebServiceHostFactory” to the ServiceHost directive. This is the configurationless model. This factory will dynamically set up an instance of the WebServiceHost in response to requests. It will set up a default endpoint, if appropriate, with the binding set to webHttpBinding, our REST-Friendly binding.
- So, now we are all set up from a configuration(less) poing of view. Now we just need to write the service for the code.
- That’s it. We are ready to test.
- Run your project (F5) (remember that we are still pointing at Azure Table Storage in the cloud. You might want to change your configuration settings back to point at local developer storage
- Change the URI in Internet Explorer to the following: http://127.0.0.1:81/WineService.svc/wines Here is what you should see:
- Cool, our service is working. We now need to change the ResponseFormat back to Json. Change the ResponseFormat to WebMessageFormat.Xml in WineService.svc.cs.
Create Our Silverlight Component
We are going to build a Silverlight component that will consume the RESTful service we just created. In this post, we will start building out the catalog component. If you remember back to the first screencast, this is the portion of the application where the wines were exposed and you were able to page through it. I will implement the paging in a future post. What we are going to do here is to:
- Create a ListBox in Xaml
- Wire up an event handler for the loaded event
- Call our RESTful service
- Deserialize the response to a collection
- Bind our ListBox to the collection
- Pretty Up the Xaml
Well, now that we know what we are going to do, let’s get to doing it:
- Add a Silverlight Application Project to the Solution: Right-Click the Solution > Add > New Project > Silverlight > Silverlight Application
- Leave the defaults on the Add Silverlight Application. These choices will add this project to the Silverlight Applications for our web role, will create 2 test pages that by default contain a control from our project and setup debugging.
- Add a ListBox directly under the grid.
- Wire up a Loaded Event Handler to fetch the Wines
- Open Page.xaml.cs
- Wire up the event handler in the constructor
- Add a private property that returns the root Uri to the web. We will use this to calculate the Uri to our RESTful service
- Code up the event handler for the loaded event. Here we want to call our RESTful service
- Start by using the helper method we created earlier to calc the Uri to our RESTful service
- Create an instance of the WebClient class. This is the simplest HTTP networking class to use in Silverlight.
- We are going to call the OpenReadAsync method to issue an HTTP GET to our RESTful service. The call is asynchronous (as are all networking calls in Silverlight), so we must first wire up an event hander to handle the response.
- Add references to System.ServiceModel.Web and System.Runtime.Serialization. We need these to use the DataContractJsonSerializer to deserialize the response.
- OK, so now we are ready to write the callback method for our HTTP GET to our RESTful service. This is where it may seem a bit tricky. Remember that our service returns a List<Wine>. The challenge we will have is that our Silverlight control has no concept of what a ‘Wine’ is. That class exists on the server, and the control is on the client. So what we need to do is to create a Wine class on the client that we can use to deserialize our response.
- Write the event handler for OpenReadCompleted. We will be passed the response as a Stream in the EventArgs. We will use the DataContractJsonSerializer to deserialize the response. Once deserialized, we can simply set the ItemsSource of the ListBox.
- Test It
- Pretty it up. We got it working, but it isn’t very nice looking.
- Open App.xaml
- Add the Layout Styles and the ListBox Styles
- Open Page.xaml
- Delete the Height and Width attributes from the UserControl node
- Update the layout of the control. Replace the Xaml with the following:
- Add a DataTemplate to the ListBox
- Copy the Images Directory from the Web into the Silverlight Project
- Test It
Well, now we’re getting somewhere! It’s starting to look pretty good. In the next post, I will implement paging, so don’t simply fetch all of the wines, rather we fetch a few at a time. In future posts, I will illustrate how to use SOAP services instead of REST, implement the cart, security, and much, much more. Until then…