Share via


The Canonical REST Entity Service

Recently I was doing a review of some .NET 3.5 WCF REST code based on the REST Starter Kit to see what it would take to move it to .NET 4.

The more I looked at the code and thought about it deeply I realized that the mechanics of exposing a service over HTTP are not the hard part.  What is difficult is to get the semantics of HTTP right.  After spending some time reading through the HTTP spec I took a stab at creating the Canonical REST Entity Service

“ca·non·i·cal [ kə nónnik'l ] conforming to general principles: conforming to accepted principles or standard practice'”

What I was after was a set of requirements that I could verify about the way in which a REST Entity Service should behave.  Here is what I came up with.

First of all I learned that Canonical is spelled with 1 n and not two as in “Cannonical” [sic] which I used all over the place in this code so… sorry. 

Watch

Get Microsoft Silverlight

Download

Canonical REST Service (MSDN Code Gallery)

Canonical REST Entity Service URI Map

Base URI: https://tempuri.org/Resource where Resource is the name of the REST collection (i.e. Customers, Orders etc.)

Web Formats XML and JSON are supported for all request/response messages

URI Template HTTP Method Description Status Response Content Response Contains
/{key} GET Gets a resource by key 200 OK Serialized resource
      304 Not Modified Empty
      400 Bad Request Empty or Serialized error message
      404 Not Found Empty
/?skip={skip}&take={take} GET Gets a list of resources starting with skip+1 and returning take 200 OK Serialized resources
      400 Bad Request Empty or Serialized error message
/ POST Adds a resource to the collection 200 OK Serialized resource
      204 No Content Empty
      400 Bad Request Empty or Serialized error message
      409 Conflict Empty or Serialized error message
/{key} PUT Adds or Updates a resource identified by {key}. Some services might not allow add with PUT. If you return the updated resource, return 200. If you don't return 204. 200 OK Updated resource
      204 No Content Empty
      400 Bad Request Empty or Serialized error message
      404 Not Found Empty or Serialized error message
      409 Conflict Empty or Serialized error message
/{key} DELETE Removes the resource identified by {key}. If you return the resource removed, return 200. If you don't return 204. 200 OK Deleted Resource
      204 No Content Empty
      400 Bad Request Empty or Serialized error message
      404 Not Found Empty or Serialized error message
      409 Conflict Empty or Serialized error message

GET TESTS

GET Spec https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

Tests GET /{key}

  1. GET MUST return a resource given a key if the resource with that key exists
  2. GET MUST return 400-BadRequest if the key is invalid
  3. GET MUST return 404-NotFound if the key is not found
  4. GET MUST return 304-NotModified if Conditional GET conditions are met using If-None-Match
  5. GET SHOULD return an ETag header

Tests GET /?skip={skip}&take={take}

  1. GET MUST skip {skip} resources in the collection and return up to {take} resources.
  2. GET MUST return resources starting with the first one when {skip} is not defined
  3. GET MUST return zero resources when {skip} is greater than the number of resources in the collection
  4. GET MUST return 400-BadRequest if {skip} is < 0
  5. GET MUST return zero or more resources when {take} is not provided
  6. GET MUST return 400-BadRequest if {take} is < 0

POST TESTS

POST Spec https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

Tests POST /

  1. POST MUST append a valid resource to the resource collection using a server generated key and return 201 – Created with a location header, entity tag and entity body
  2. POST MUST return 400-Bad Request if the entity is invalid
  3. POST MUST return 409-Conflict if the entity conflicts with another entity
  4. POST MUST ignore writes to entity fields the server considers read only

PUT TESTS

PUT Spec https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

Tests PUT /{key}

  1. PUT MUST Update the entity identified by the URI if it exists and return 200-OK with the modified entity and etag header
  2. PUT MAY Add a new entity using the key provided in the URI and return 201-Created with entity location and etag
  3. PUT MUST respect the Precondition If-Match
  4. PUT MUST be Idempotent
  5. PUT MUST NOT alter the key of the entity so that it does not match the key of the URI
  6. PUT MUST return 400-BadRequest if the entity is invalid
  7. PUT MUST return 400-BadRequest if the key is invalid
  8. PUT MUST ignore writes to entity fields the server considers read only
  9. PUT MUST return 404-NotFound if the server does not allow new entities to be added with PUT

DELETE TESTS

DELETE Spec https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

Tests DELETE /{key}

  1. DELETE SHOULD delete an entity that exists and return 200-OK with the deleted entity or 204-No Content if the response does not include the entity
  2. DELETE SHOULD be idempotent
  3. DELETE SHOULD return with 412-PreconditionFailed if no matching entity for If-Match etag
  4. DELETE SHOULD succeed if matching entity for If-Match etag
  5. DELETE SHOULD succeed if wildcard used in If-Match etag
  6. DELETE SHOULD return 202-Accepted if the request to delete has not been enacted
  7. DELETE SHOULD return 400-BadRequest if the key is invalid

Comments

  • Anonymous
    July 23, 2010
    Finally, my favorite WCF REST solution is getting some well deserved love! Thank you!

  • Anonymous
    July 25, 2010
    I wonder what the RESTful bigots will say about this?

  • Anonymous
    July 25, 2010
    @DaRage - well I hope we can dialog about it and make it better.  I'm actually trying to build something that is faithful to the ideals of REST.

  • Anonymous
    July 29, 2010
    The comment has been removed

  • Anonymous
    July 29, 2010
    The comment has been removed

  • Anonymous
    July 29, 2010
    @DaRage - Just wait - the team is working on some really cool new stuff for REST that will give you what you are looking for (I hope).

  • Anonymous
    July 30, 2010
    What do we need to install to open this in Visual Studio 2010.  A pristine install of VS 2010 Premium says the project type is not supported.

  • Anonymous
    July 30, 2010
    @VS2010 Compatible... I'm not sure wht the issue is.  It is just a Web Project, a Test Project and a Class Library project.  Nothing unusual there.

  • Anonymous
    July 30, 2010
    DaRage - I agree with you, and your remarks seem to echo my concerns that even if the WCF team might be trying to RESTify WCF, at least in my opinion, they are not succeeding in a coherent and fully supported manner that builds confidence. So then if RESTifying WCF is not the preferred approach, should there be a RESTified MCV with full tooling/testing support for RESTful programming? Or should it be a new framework entirely devoted to REST and only REST? ronjacobs - Is the really cool new stuff for REST built on top of WCF, on top of MCV, or as discussed here, completely independent of either WCF or MCV?

  • Anonymous
    August 01, 2010
    @DaRage - The new stuff is new stuff :-)   What really matters is what it does and how it works.  When the time is right (hopefully soon) we will begin sharing it with you on Codeplex to get your feedback. My first goal will be to update this sample based on the new stuff - that is why I built the tests - they will be a good barometer for insuring the new stuff is really working as it should.

  • Anonymous
    August 02, 2010
    @DaRage, @Carl Thanks for all the feedback. I am driving our HTTP/REST story going forward. I hear all your concerns. We are not looking to simply retrofit on top of our existing stuff. We are looking at a pure resource oriented model, and how to best deliver on that. That doesn't mean we won't use some of our existing bits, but we are really focused on the ideal experience over how can we just use what we have. We're also focused heavily on involving the community both inside and outside of .NET in the work we are doing. This includes getting source out there sooner which is something we're working on. I have posted early thinking on this here: codebetter.com/.../resting-from-mef-or-the-mef-dealer-is-at-rest.aspx I'd be happy to chat with either of you more to hear your concerns. Thanks Glenn

  • Anonymous
    August 03, 2010
    So this isn't SOAP or OData, but this returns XML of a Resource type.  Also this is NOT WCF Data Services but looks like WCF Services.  NOW I am confused as what to use.  

  • Anonymous
    August 04, 2010
    @Allan - Hang on - we are mixing things up a bit.  What I built is based on WCF WebHttp Services with stock .NET 4 and a set of tests that can verify a service behaving correctly. What Glen is talking about is next-gen stuff