A post about RESTful services

Introduction

This is the first article in a planned series of blog posts. There will be two or three posts in all. Today the All-In-One Code Framework sample Story Creator has a web role, which contains a RESTful service that allows you to upload stories to Windows Azure. One of the potential features in the next version of Story Creator is to use Windows Azure ACS (and possibly Windows Live Connect) to protect this service. So this post talks about how to work with RESTful services, and future posts will talk about how to use ACS.

Many of you already know how to work with REST services. In this case, you can simply ignore this post. However, I’ve seen quite a few people try to change an existing SOAP service to use WCF’s WebHttpBinding, and then think they get a REST service. That's understandable as most WCF books (unfortunately) start with a lot of chapters talking about ABC (address, binding, contract), and use a single chapter at the end of book to discuss WebHttpBinding, and most getting started tutorials about WCF talk about the same ABC of WCF as well.

However, WebHttpBinding doesn't have to be REST service. In this post, I’ll first talk about what it means by a true RESTful service, and when to use REST. Finally, I'll also briefly talk about how to create/access simple REST services. But the how to part is not the main goal. It's just there to give you some actual code. You can find a lot of other samples on the internet. The how to part will focus on WCF Web API and Windows Phone.

What is REST

Essentially, a REST service is a service that uses the HTTP protocol to deliver resources to clients, or upload resources from clients to server. We can say a REST service is resource centric. This is different from SOAP, which is operation centric. In SOAP, you use a generated proxy to invoke remote service operations similar to invoking local methods.

You can think a classic web site (not client side web application) as a REST service. It delivers web pages (resource) to clients, and may allow clients to upload new pages.

As another example, consider a ticket system. If you take the operation oriented approach, you will define operations like GetTicketByDate, BuyTicket, and so on. But if you take a resource oriented approach, instead of thinking about those operations, you think ticket as a resource. Then you define how client may interact with the resource using HTTP requests.

For example:

  • GET https://[your domain]/tickets

Return all tickets.

  • GET https://[your domain]/tickets/1

Return the ticket whose ID is 1.

  • GET https://[your domain]/tickets?startdate=2/1/2012

Return all tickets since 2/1/2012.

  • POST https://[your domain]/tickets

Create (buy) a new ticket.

  • PUT https://[your domain]/tickets/1

Modify the ticket whose ID is 1.

  • DELETE https://[your domain]/tickets/1

Delete the ticket whose ID is 1.

Essentially, you allow clients to make HTTP requests regarding this resource.

That is the basics of REST. You can find more information on https://en.wikipedia.org/wiki/REST.

Remember, REST does not simply mean WebHttpBinding. It is a way to design your application. It is resource centric. You can use WebHttpBinding to build SOAP style operation centric services that do not use SOAP standard, but they're not REST services.

When to use REST

Now that you understand what it really means to be a RESTful service, a natural question is when to use it (or why do we need it at all). How about briefly reviewing the history of web service? I think you'll find the answer yourself.

A brief history of web services

When the century begins, there was only one kind of web service: SOAP service. This has been the case for a long time. I still remember when I first worked with an ASMX web service when I was still in university. That was long long ago (in 2005). SOAP was invented mainly because we need interoperation between different platforms (at that time, it was mainly between .NET and Java). As long as a service follows the SOAP standard and a client platform supports SOAP standard, even if client and service are on completely different platforms, they will be able to talk with each other. Actually my project for my Web Services course was exactly a task management system that contains a .NET client and a Java service. They worked together nicely. But that was based on SOAP 1.1, without any additional features such as WS-Federation.

However, SOAP has a lot of problems. For one thing, its format is not very simple. As new standards come out, the format becomes even more complex. SOAP 1.2 is much more complex than SOAP 1.1. The standard guys are doing a good job to standardize many things, such as security. But almost every standard related to SOAP is very complex. To name a few: WS-Addressing, WS-Security, and WS-Federation. This has introduced a lot of problems. Very often, a client needs to access multiple services. Perhaps service A uses SOAP 1.1 without any security, but service B uses SOAP 1.2 and WS-Federation. Thus client must understand both of them. In addition, sometimes it is not easy to figure out which set of standards a service needs. Is WS-Addressing required by this service? Does that service use WS-Trust or WS-Federation? So in the end, SOAP does not solve the interoperability problem very well, unless both client and service follows simple standards as I did in my primitive university course project :).

Around 2005, people started to talk about SOA (service oriented architecture). I remember one of my instructors complained the world changed too frequently, that he was unable to teach us the latest technologies :). Well, let it be, as usually the technology world changes for good. SOA, no matter how similar the name looks, is actually not SOAP. It is an architecture. It evolved from traditional N-tire architecture. You expose your business logic as services (web service is a kind of services). A service is a reusable component. A client picks up one or more services. For example, traditionally, you may have a large system (say, employee management system). The system itself is complete, with an ASP.NET presentation layer, a business logic layer, and a data access layer. But it is not easy to extend it. So you try to divide it to smaller pieces. You may build an employee service, a salary service, a performance service, and so on. Your existing ASP.NET application uses all of those services. You can build an additional WPF application that visualizes the salary data, so it only needs salary service. If the services happen to be built with standards, very likely someone else can create a none .NET client that uses some of the services. When a service's implementation changes, as long as the service contract remains the same, client applications do not even need to be aware of the change.

SOA remains very important today. However, remember SOA is not SOAP. You can build a service using SOAP. But SOA is rather about architecture. In SOA, a service is meant to be reusable. Interoperability is also a goal, but not mandatory. It is wrong to think you're adopting SOA simply because you use web service. For example, when building Silverlight applications, you have to use a WCF service to access database. But if the only goal is to make the Silverlight application talk with database, that is not SOA. Actually a main goal of WCF RIA Services is to allow you to use traditional N-tire architecture in a Silverlight project to quickly build a line of business solution. Clearly those solutions do not adopt service oriented architecture.

Around 2006, people started to talk about REST. The main goals of REST are to simplify web services and utilize HTTP. As pointed out above, SOAP can very complex. It is difficult to access a SOAP service without using a tool (such as svcutil) to generate a client proxy. REST services, as you've seen above, use HTTP protocol. All you need to do to access a REST service is to make an HTTP request. At first, REST was commonly used for web clients (AJAX), mainly because there was no good tool to generate client proxies for JavaScript applications. Later people found out you can access RESTful services from almost any platforms. It solves the interoperability problem nicely, yet it's easier to consume compared to traditional SOAP based web services (at least without a proxy).

Today the client side of REST continues to be supported on all major platforms, both Microsoft and third party. Actually it's almost impossible to find a platform that does not support REST client stack, as it is merely HTTP. SOAP, on the other hand, is not supported out of box by a lot of platforms, including iOS and Android (although third party libraries exist). Windows Phone supports the simplest SOAP out of box: SOAP 1.1. It doesn't support more complex standards.

Considerations when using REST

OK, enough about the history. Now that you understand why REST came out at the first place, it is easy to see where to use it. Essentially, if you want better interoperability, if you want your service to be consumed on a bunch of devices, if you don't want to use too many complex standards, if you want your service to be easy to consume, it is recommended to use REST.

However, REST does introduce some challenges. For one thing, there're so many standards related to SOAP, and the standards weren't created for no reason. For example, WS-Federation allows you to perform federated authentication. But it doesn't support REST. So new standards have to be created. To avoid the old problem, new standards have to be simple. But simple also means fewer feature sets. The standard that allows you to perform federated authentication for REST services is OAuth, which I plan to talk in a future post. Those new standards may be nice. But they have not been tested by time and practice. So perhaps there're problems in it. Who knows? If you are building a mission critical service, you need to be careful on which standards to use. (However, you don't need to worry about OAuth, as it is already used by a lot of major online services, such as Windows Live and Windows Azure ACS.)

In addition, SOAP almost requires you to follow standard to word. It has detailed specifications on the request/response format. For example, SOAP body must use a specific format of xml, and binary data must be sent using MTOM format. Complex as it may be, it does perform a good job, as all services must follow a single set of standards to claim they're SOAP compliant. REST does not have such detailed requirements (kind of CMMI vs. Agile, right? I like Agile by the way!). Actually it allows you to use arbitrary format, be it xml, JSON, binary, or anything else. You have a lot of freedom. But you also have responsibility to make sure it is easy for clients to consume your service. Remember there's no add service reference when it comes to REST. For example, it is easy to generate a response using DataContractSerializer, and deserialize it on a .NET client. But what if the client is iPad? What if the client is a JavaScript/C++ Metro application? As another example, to increase performance, it may be intended to use binary format. But how many clients understand your binary content? So you need to double check how you design the request/response format. Use binary format only if you're sending/receiving binary files. Use DataContract(Json)Serializer only if your object is not too complex.

There have been some attempt to standardize REST format. Common examples are RSS and AtomPub. You need to consider them when appropriate. WCF Syndication API allows you to build RSS and AtomPub feeds. OData is another sample built on top of AtomPub and a specific JSON format. On .NET platform, it is easy to build OData compliant services with WCF Data Services. Use those standards as you see fit, but do not force yourself. REST does not force you to follow a specific format.

Build a simple REST service using WCF Web API

Finally, let's see how to build and access RESTful services as we did in the Story Creator sample. Remember, it's more important to understand what is REST and when to use it. You may need more time and experience to understand those topics. How to use it is a relatively simple topic, and can be picked up quickly. Here we'll briefly talk about it. You can find a lot of samples on the web.

On .NET platform, there're three ways to create REST services (perhaps more): Generic handler, ASP.NET MVC controller, and WCF. When using WCF, there're again two ways to build the service: Use .NET 4's built in feature (such as WebServiceHost), or use WCF Web API. Our Story Creator was built with WCF Web API. So that's what we're going to talk about today. But actually you can use anything you like. I want to point out ASP.NET MVC controller can actually be used as a REST service. Do not limit your imagination!

To use WCF Web API, you need to first download it from https://wcf.codeplex.com/ (you can also use NuGet if you want). The latest version is Preview 6. Note currently WCF Web API is a preview version (or beta if you like). So there may be several break changes in the future. Actually our original Story Creator was built with Preview 4. Preview 5 introduced a break change: Some synchronous methods have been removed. The new version of Story Creator will change as well. Today I assume you use Preview 6. Many of the features may be built-into .NET 4.5 in the future. You can already find some of them if you've used Windows Developer Preview.

To create a REST service using WCF Web API, you can start with an empty ASP.NET application, or add a new service to an existing one.

The first thing to do is to add references. You need standard WCF assemblies, such as System.ServiceModel.dll, System.ServiceModel.Activation.dll, and System.ServiceModel.Web.dll. You also need Web API assemblies. Today we only need Microsoft.ApplicationServer.Http.dll and System.Net.Http.dll. You may need more references if you want to use more features. If you plan to deploy the service to Windows Azure (as we do in Story Creator), make sure all Web API references' Copy to local are marked as true, even if you use NuGet to add them.

Then you need to register a service route in Global.asax. This step doesn't require Web API. It is a feature that is already built into .NET 4. .NET 4 allows you to use ASP.NET URL routing to register the service, and thus removing the .svc extension. The following code registers a base URI https://[your domain]/stories/. Obviously, a story is a resource.

        public static void RegisterRoutes(RouteCollection routes)

        {

            routes.Add(new ServiceRoute(

                "stories",

                new HttpServiceHostFactory(),

                typeof(StoryService)));

        }

        protected void Application_Start(object sender, EventArgs e)

        {

            RegisterRoutes(RouteTable.Routes);

   }

Now you need to create a service class. Unlike normal WCF services, you don't need a separate interface to define service contract and operation contracts. Actually there're no operation contracts, as REST services are resource centric instead of operation centric.

In the service class, you can define some methods. The name of methods do not matter (they matter in SOAP unless you define custom namespaces), although usually use simply use Get, Post, and so on. What's really important is HTTP method and UriTemplate. To define HTTP method to GET, you use WebGet. To use other methods, you use WebInvoke with a specific method, such as:

[WebInvoke(Method = "PUT")]

UriTemplate defines the relative path. If it's empty, base URL will be used. This is useful if you want to return all resources, or create new resources. For example, in Story Creator, when client makes a GET request to https://[your domain]/stories/, we return all stories. When the client makes a POST request to the same URI, we create a new story. The same URI can support multiple methods. You can also use query string to define parameters, which will be mapped to CLR method's parameter. For example, in Story Creator, when the Windows Phone client finishes uploading all photos to Windows Azure blob using the SAS URI, it makes a PUT request to the web role to tell it the story can now be committed:

[WebInvoke(Method = "PUT", UriTemplate = "{id}?commit={commit}")]

public HttpResponseMessage Put(HttpRequestMessage request, string id, bool? commit)

You can refer to the existing StoryCreator sample's web role project for detailed information. For now, I'll only walk you through creating a basic GET request. And since service implementation is not important, I'll use a dummy xml document. Please note the use of WebGet and UriTemplate, as well as how to create a response that corresponds to HTTP standards. In the response, we set status code to OK (200), and set content-type to text/xml. This is required if you want your service to be interoperable.

public class StoryService

    {

        [WebGet(UriTemplate = "")]

        public HttpResponseMessage Get(HttpRequestMessage request)

        {

            XElement stories = new XElement("stories", 

                new XElement("story", new XAttribute("name", "My first story")),

                new XElement("story", new XAttribute("name", "My second story")),

                new XElement("story", new XAttribute("name", "My third story"))

            );

            HttpResponseMessage response = new HttpResponseMessage();

            response.StatusCode = HttpStatusCode.OK;

            response.Content = new StringContent(stories.ToString(), Encoding.UTF8, "text/xml");

            return response;

        }   

We didn't use a serializer above. But you can definitely use one if you want. Actually you can return a complex CLR type, which will be serialized automatically. Just be careful as the automatic serialization may not always give you a decent format. You can find additional information on https://wcf.codeplex.com/.

Finally, to use WCF Web API, you must enable ASP.NET compatibility mode. That's simple. Add the following to web.config:

<system.serviceModel>

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>

  </system.serviceModel>

You don't need to configure ASP.NET compatibility mode on the service implementation class, as you do in a normal WCF service.

You don't even need to configure bindings, endpoints, and so on. In case you really want to (for instance, increase some max*** settings), you can do so when creating the service route in Global.asax.

Access REST services from Windows Phone

To access a REST service from Windows Phone, you can use either WebClient or HttpWebRequest. It's already very late and I'm tired. So I'll only talk about WebClient today. It's easier to use. HttpWebRequest is needed for more advanced requests. For example, we will need it to work with OAuth in a future post.

private void RetrieveStoriesAsync()

        {

            WebClient webClient = new WebClient();

            webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(StoriesRetrieved);

            webClient.DownloadStringAsync(new Uri(serviceBaseAddress));

        }

        private void StoriesRetrieved(object sender, DownloadStringCompletedEventArgs e)

        {

            if (e.Error != null)

            {

                MessageBox.Show("Error downloading stories.");

            }

            try

            {

                this.storiesListBox.Items.Clear();

                XElement stories = XElement.Parse(e.Result);

                foreach (var story in stories.Elements())

                {

                    this.storiesListBox.Items.Add(story.Attribute("name").Value);

                }

            }

            catch (XmlException)

            {

                MessageBox.Show("Unexpected result from service.");

            }

        }

There's nothing special in the above code. We just made an HTTP request, used LINQ to XML to parse the result xml data, and displayed them inside a ListBox (in the real Story Creator, MVVM and data binding is used). Note Windows Phone only supports asynchronous requests (same as Silverlight).

Conclusion

Today you see what it really means to be a RESTful service, and when to use REST. A project will not be attached this time, as I'm preparing a more interesting prototype with OAuth integration, which may be ready the next time I write a blog post. Once again, I want to emphasize the most important task is to learn how to think in a RESTful way (resource centric), and when to use it. Otherwise you may end up with a service that is actually not a REST service, while you think it is, or use REST in a complete wrong way. After you understand those topics, it is easy to learn how to create and consume REST services. But you still need to do some real practices by building applications, not simply reading.

Recently I heard a joke: "Theory means you know everything but nothing works. Practice means everything works but you know nothing. So theory plus practice means you know nothing and nothing works." But in reality, we know "Theory plus practice means you know everything and everything works". That's why I thought I need to write those blog posts, to further my own understanding about the theories, and do more practical work. Hope they will also help you. :)