In this entry I would like to round up where we have got to so far with this web service. Over the last 13 posts we have developed a fairly functional web service that sticks pretty much to the ideas presented in Leonard Richardson and Sam Ruby’s book RESTful Web Services. It is developed using C# using the (currently Beta) MVC framework from Microsoft that extends the ASP.Net framework.
As an aside, I’ve also taken on board a comment from Stephan and moved some of the reusable classes into their own assembly.
So here are the features so far.
A RESTful web service should expose each of its resources through at least one unique URI. This contrast with a SOAP based web service where the same URI can expose many resources.
We didn’t have to write much code to gain Addressability, MVC lets us expose an infinite number of resources through an infinite number of URIs. It does this by allowing the developer easy access to the new ASP.Net routing functionality. By the end of the second post we had routing working for us.
The second feature we tackled was multiple representations. This is the ability of the web service to serve the same resource information in different formats. By the end of the third post changing the URI caused the web service to return one of three representations:
- XHTML - Leonard Richardson and Sam Ruby’s preferred representation;
- XML – this required an XsltResult class to be written. This class used a similar mechanism for finding the XSLT to apply to the outgoing XML as is used by MVC to locate the View to use. Using a transform on the data allows us to keep a clean separation between the web service and its clients.
In post four I introduced a fourth representation that I have come to rely upon during the development, Help. This representation generates XHTML but also adds help information related to each resource and a client side test harness. This test harness allows a potential client developer to experiment with the web service.
To be considered RESTful a web service should expose a limited, well known interface. If the web service is based on the HTTP interface it should consist of a number of “verbs.” All resources will expose a subset of the verbs available and those verbs will have the same effect on all the resources.
The first few posts only used the GET verb, which returns a representation of a resource. It is considered “Safe” as it has no material effect on the resource.
Posts 5a and 5b introduced the other part of a Uniform Interface, well known response codes. In those posts we looked at returning status codes and catching all possible errors raised by ASP.Net and the MVC framework.
Post 6 started to restrict the verbs accepted by a resource. The read only resource we started with was updated to only respond to the GET verb.
In post 7 a read / write resource was introduced so we could investigate correctly supporting more of the HTTP verbs. We back tracked on how to deal with different verbs. Also to help with the allowed-verbs header the BaseController called the abstract AllowedVerbs property.
The first additional HTTP verb was introduced in post 8. By supporting the DELETE verb, the web service allowed a resource to be removed. DELETE is an “Idempotent“ verb, which means it can be called multiple times by the client against the same resource without any ill effect.
Post 10 introduced another “Idempotent” HTTP verb, PUT. This raised the issue of how to deal with an incoming XHTML representation as these require the full XHTML DTD to be available to the XML parser. Post 11 solved that issue.
In post 12 we added support for creating resources using the HTTP POST verb. POST is neither Safe nor Idempotent and should be treated with care. With POST we had completed the Uniform Interface for our web service. There are other verbs commonly used with HTTP, these could be added easily if required.
The ninth post introduced overloading of the POST method. This technique allows clients that don’t support the entire HTTP verb set to re-use the POST method to make DELETE and PUT requests. We had to create our own version of the AcceptVerbsAttribute that not only filtered by HTTP verb, but (if a POST is used) would also looks for an _method query string variable.
I believe we’ve got a pretty comprehensive RESTful service now. However, there is still at least one major feature to deal with, “Connectedness.” As Leonard Richardson and Sam Ruby say:
In a well-connected service, the client can make a path through the application by following links and filling out forms. In a service that’s not connected, the client must use predefined rules to construct every URI it wants to visit.
So that is our next step. In the meantime, here is the refactored code: RESTfulMVCWebService11.zip (86.72 kb)