Freigeben über


Talking Points: WCF and RESTful Services (Part II)

In Part I  we saw how WCF has been extended to support RESTful services natively! We discussed how the primitive constructs of the web (HTTP Methods) enable communication patterns that are simple yet very flexible and powerful. We saw how WCF serves as the building block within our platform to extend services to the cloud. We also explored the role of AJAX and Web Feeds  (RSS, Atom) in enabling a new programming model that builds upon the progress achieved in making the web a programmable environment.

This time we will focus on some of the mechanics that make it all work with general observations on additional aspects of the technology.

WCF Dispatching

We already know that WCF’s main purpose is to abstract away network and security and allow developers to concentrate on writing code. A developer writes code inside of methods on what is commonly known as the “service type”.

WCF, by default, routes network messages to these methods based on the SOAP Action header. This is done by the “dispatching layer” in WCF which is responsible for figuring out what method to call when a network message arrives.

WCF implements SOAP using the standards, with one URI for each service endpoint. In WCF 3.5, a new dispatcher is added which dispatches based not on SOAP action, but instead based on the URI + the HTTP Verb. This allows a WCF endpoint to implement a RESTful approach, because in REST we expose resources at specific URIs that respond to particular HTTP verbs.

By annotating methods with new attributes, the new WCF dispatcher is able to route messages coming into particular URIs to particular methods, based on the verb of the request. All the other familiar WCF programming model constructs are the same. In fact, in some cases WCF definitions can be used with both SOAP and REST endpoints.

In a typical WCF service endpoint we have messages coming in from some network protocol. WCF allows us to plug in different protocols (like HTTP, MSMQ, TcpIP) along with different protocol channels (like WS-Security, WS-ReliableMessaging, etc). The MessageEncoder is responsible for taking the network message format (which might be XML or even binary) and turn it into something that WCF can understand. The dispatcher then gets involved and figures out what method to call on the classes you write.

The Web dispatching layer reduces this down to the HTTP transport channel, the TextMessageEncoder (with MessageVersion set to none – which effectively turns off the SOAP envelope), and then the new dispatcher. So when messages arrive for a particular URI, a match is made to one or more methods, and then the verb is checked. If a match is made, the message is then passed to that appropriate method.

WCF 3.5 REST basics summary

  • UriTemplate: Literal and replaceable path URI path segments
    • This allows URIs to be declared with both literal and replaceable path segments (like /users/{userid}). We use this syntax to tell WCF what URIs we want our methods to respond to, with the replaceable path segments passed into our methods as parameters.
  • WebGetAttribute: Verb GET - UriTemplate property defines URI andWebInvokeAttribute: Verb * - Method property (POST is default)
    • WebGetAttribute, and WebInvokeAttribute, that get placed on our WCF OperationContract methods. The WebGetAttribute tells WCF that a particular method should respond to GET requests. The WebInvokeAttribute defaults to POST, but can be customized via its Method property to use the other verbs in the uniform interface. Both WebGetAttribute and WebInvokeAttribute have a UriTemplate property to allow customization of the URI at the method level.
  • WebHttpBehavior: Replaces dispatcher (HTTP + VERB)
    • Endpoint behavior that replaces the default SOAP dispatcher (the one based on SOAP:Action) with the one that does the dispatching based on URI+Verb
  • WebHttpBinding: HTTP+TEXT (no soap)
    • Creates a WCF channel stack with just the HTTP transport and the TextMessageEncoder, with MessageVersion set to None
  • WebServiceHost/WebServiceHostFactory: Automatic config/Automatic config in IIS
    • A custom ServiceHost-derived class that can automatically configure RESTful endpoints, and WebServiceHostFactory is a ServiceHostFactory-derived type that can be used in managed (IIS) hosted scenarios.

AtomPub

The support built into WCF for feeds is of course built on top of the base functionality we discussed on Part I. Typically, we use WebGet to expose a feed endpoint from a particular URI. The basic idea behind the WCF support for feeds it to abstract away from the developer the need to know the various feed formats (in this version of WCF that’s RSS 2.0 and Atom 1.0). This is done by separating the data from the serialization model.

As a developer, I can simply take my data and push it into the WCF OM. I then take the WCF OM and pass it to the formatter. The formatter takes care of turning the WCF OM (which is layered on top of my data) into the correct feed format.

The WCF OM is closer to the Atom model, since the Atom model is as we said before, a little richer in terms of its data. AtomPub is quickly becoming a common way to expose a RESTful service when the resources fit the AtomPub model (collections of collections of things). It’s been adopted by Google and Microsoft Live as the way to expose their services functionality.

3.5 SP1 adds support for:

  • ServiceDocument (which is the top-level document in an AtomPub endpoint, which contains one to n workspaces. A workspace can indicate things like what media types a collection can accept, as well as just providing an organizational structure around a set of feeds.
  • CategoriesDocument (that contains the list of official categories or tags for a collection).

Tooling support

Its clear that SOAP/WS-* has the advantage in the tooling area. This is because SOAP services can expose WSDL and Policy information that client tools can easily consume to build proxies. On the REST side there are two competing camps. One camp wants to create RESTful metadata, and so there are open projects like WADL (Web Application Description Language) out there, and some people feel that WSDL 2.0 can be used to describe RESTful services.

ADO.NET Data Services, a full REST-based data service, exposes metadata, but it isn’t in any sort of a standard and only works with “Add service Reference”.

The other camp believes that metadata-generated clients causes too much coupling between a client and service. For this camp, the hypermedia constraint is extremely important in building loosely coupled clients that can get the “root” resource from a service and then just drive off of the links in that resource.

Security

Security is something you often hear is better in the SOAP world. Of course WS-* does provide for end-to-end message level security across transports – but in the wild you generally find people using SOAP over HTTP, and often times using SSL.

Since REST is built on the framework of the Web, it can simply use the same security model you use on the Web. Typically that is SSL, using either basic or certificate authentication.

Federated security is another emerging technology, and the WS-* side has an lead in that area, but there are emerging standards in the web world as well (OpenId and OpenAuth), and likely federated solutions will support both (.NET Services identity services support both SOAP and REST clients).

Processing / Transactions

Another issue that comes up is the feeling that REST is really just about CRUD. Certainly CRUD maps well onto the uniform interface, and when learning REST this is generally the way people think about REST. They have a hard time thinking about more than CRUD.

Generally the canonical example of a bank account represented as a resource makes sense to people. But what happens when you throw a transfer scenario onto that service? This is where people tend to feel more comfortable with RPC (like SOAP).

The way people in the REST camp look at this problem as one of refactoring your resources. Instead of creating a “method” for an account transfer – you create a “transfer” resource. The resource is a temporary resource that represents the transfer. Since REST has no notion of transactions this also makes some people nervous, and the idea of conditional PUT (using etags) can provide protection against processing the transfer more than once.

Service Consumption

How do you consume RESTful services using .NET?

HttpWebRequest/HttpWebResponse is one way to go (and probably *the* way to go if you are in the hypermedia/loosely coupled camp). Although you generally have to program at a pretty low level, using the DataContract or XmlSerializer to create request bodies and read responses.

WCF’s programming model is symmetrical, and works as a client programming model as well. But since there isn’t any support for metadata, you have to hand code all of the interfaces. You can generate type definitions by using Visual Studio’s XML functionality (to infer a schema from an XML instance, and then use WCF’s svcutil to generate a class definition).

When consuming feeds you can use the WCF SyndicationFeed class (or ServiceDocument if you are consuming AtomPub). In the AJAX scenario of course there is the auto-generated client.

Purity (Purists vs Pragmatics)

The Purist problem is one that actually makes some people turn away from REST. There are a number of people out there that are very religious about REST and are very vocal about critiquing people they think are doing REST *wrong*.

What’s really important is to understand the architectural style and constraints of REST and what advantages each of them provide. If you decide to build a service using most, but not all, of the constraints as long as you understand what you are giving up in exchange for ignoring one or more of the constraints you still will be taking advantage of the features of the other constraints.

Some developers may refer to “Lo-REST” and “Hi-REST”, where Lo-REST is sort of pragmatic and Hi-REST is more pure. We won’t get into it here :-)

Conclusion

Fortunately we live in a universe of endless diversity (so it seems!) from stars to cereals! So it should be natural to expect the same pattern reflected in everything we do in IT from programming languages to distributed communication methods. REST, as we have seen, serves to further expand the diversity already present in WCF, and therefore our platform; to provide the flexibility necessary to enable Cloud computing and Software + Services. This trend will evolve into a mature new platform where diverse systems and solutions are connected together in meaningful ways targeted at the specific needs of everyone.

References

For everything RESTful in WCF go to MSDN here is the source.  and for everything REST on channel 9 here is the full collection.

Have a RESTful week!

Joel Reyes

Technorati Tags: Joel Reyes,REST,RESTful Services,RESTful,WCF+REST

Comments