RESTful Web Service in WCF

The RPC-based services presented thus far on this blog have used standard SOAP and WS-* encodings over an HTTP transport. This is evidenced by the wsHttpBinding binding in the service configuration. RPC is a traditional client/server architecture whereby the client calls a command or action on the service. The World Wide Web is constructed around a different architecture where clients request resources from a service. Resources are identified by Uniform Resource Identifiers (URI) and often contain links to other resources. This architecture is known as Representational State Transfer or REST. Consult the Wikipedia article on REST for more details.

Web services can also be constructed using the REST architecture. Such services are called RESTful. Resources on the Web are returned to your browser as, for example, HTML documents and JPEG images, are presentation oriented, and are intended to be rendered in human-readable form. RESTful services, on the other hand, return machine-readable resources as XML documents or in JSON format.

RESTful services can be created quite easily in WCF using the .NET framework 3.5. In fact configuration is much easier than with SOAP services. Here I will make the Baroque composer service that I created in my last postRESTful. First declare the service contract.

[ServiceContract(Namespace="https://patconroy.wordpress.com/service")]
public interface IRestBaroque
{
    [OperationContract]
    [WebGet(UriTemplate = "/composers")]
    ComposerCollection GetComposers();

    [OperationContract]
    [WebGet(UriTemplate = "/composers/{composerId}")]
    Composer GetComposer(string composerId);

    [OperationContract]
    [WebGet(UriTemplate = "/composers/{composerId}/compositions")]
    CompositionCollection GetCompositions(string composerId);

    [OperationContract]
    [WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "/json/composers")]
    ComposerCollection GetComposersJson();

    [OperationContract]
    [WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "/json/composers/{composerId}")]
    Composer GetComposerJson(string composerId);

    [OperationContract]
    [WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "/json/composers/{composerId}/compositions")]
    CompositionCollection GetCompositionsJson(string composerId);
}

Notice the additional attribute WebGet attached to each operation. This informs the framework that following operation is to be invoked on when an HTTP GET method is received for a certain resource. The WebGetAttribute.UriTemplate property identifies the URI of the resource that the service operation will respond to. UriTemplate is, as its name implies, a template that may contain runtime replaceable parameters. The framework parses these parameters from the requested URI at runtime and passes them in to the operation implementation as method parameters. The name in the template must match exactly the parameter name in the operation method. Additionally, the method parameter must be of type string. The framework will not convert from string to any other data type such as int. That must be done in the operation implementation, as it is in this example.

public CompositionCollection GetCompositions(string composerId)
{
    CompositionCollection compositions = null;
    int id;
    if (Int32.TryParse(composerId, out id))
    {
        compositions = GetCompositionData(id);
    }

    if (compositions == null || compositions.Count == 0)
    {
        WebOperationContext.Current.OutgoingResponse.SetStatusAsNotFound();
        return null;
    }
    return compositions;
}

Also notice how an error condition is handled. The HTTP status is set to an appropriate value, in this case 404 or “Not Found”, when an invalid composer ID is passed in. A RESTful service should utilize HTTP to its fullest extent in a manner that follows the HTTP protocol standard.

I have already mentioned that configuration of a RESTful service is much easier than a SOAP service in WCF. This is the only bootstrap code needed to self-host this service. There is no <system.serviceModel> section in the application configuration file. WebServiceHost’s default settings take care of most common scenarios. Simplified configuration is also available in IIS hosted scenarios using WebServiceHostFactory.

public static void Main()
{
    Uri uri = new Uri("http://localhost:8000/service/restbaroque");
    using (WebServiceHost serviceHost = new WebServiceHost(typeof(BaroqueService), uri))
    {
        serviceHost.Open();

        // The service can now be accessed.
        Console.WriteLine("The service is ready.");
        Console.WriteLine("Press <ENTER> to terminate service.");
        Console.WriteLine();
        Console.ReadLine();
     }
}

RESTful service GET methods can be tested simply by using a browser. I simply enter the URL http://localhost:8000/service/restbaroque/composers into the IE address bar after starting the service. The result is an XML document listing all of the composers in my test database, just as I expected.
rest_composers

I could have gotten the same data in JSON format using the URL http://localhost:8000/service/restbaroque/json/composers. This would be useful if I was creating an AJAX client that consumed this service. The WebGetAttribute applied to the service operation GetComposersJson specifies an UriTemplate of “/json/composers” and sets the ResponseFormat property to WebMessageFormat.Json.

In the future I will enhance the service with add, update and delete methods. I will also create a WPF client to consume this service. Stay tuned.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




February 2009
M T W T F S S
« Jan   Mar »
 1
2345678
9101112131415
16171819202122
232425262728  
I am a part of all that I have met;
Yet all exprience is an arch whitherthro'
Gleams that untravell'd world, whose margin fades
For ever and for ever when I move.
How dull it is to pause, to make an end,
To rust unburnish'd, not to shine in use!
Alfred, Lord Tennyson

%d bloggers like this: