Why are there 2 controllers in the ASP.NET Web API ContactManager example? REST has nothing to with it.

<some snarkiness follows/>

Rob expressed his disagreement (disgust) with the two controllers present in the sample when he made this bold statement:

image

He then went on to further elaborate on the pedantic nature of the REST community and how his making a comment unleashed a religious war on the poor soul. At some point I was dragged in which then led to Rob, Darrel and I in a long but civil debate/discussion on Jabbr.

I am not going to defend the REST community and affirm or deny whether it is pedantic or not. That’s completely besides the point and it has zero to do with the sample.

In that post he then said:

“The developer who wrote those two Controllers will avidly defend them to me, citing Fielding and quoting Wikipedia.”

That developer just happens to be me. I won’t defend them on that basis. In fact, the decision to have two controllers had NOTHING to do with REST and nothing to do with any HTTP guideline.

It was a decision based on preference not based on keeping to some elite code.

Why two controllers? (Yes I will mention HTTP here).

Mainly separation of concerns. An item resource is semantically different from a collection resource. One handles an item, the other handles a collection. I could have handled both in the same class however I chose not to and felt that it was easier to test / maintain keeping them separate. I spoke to several folks at the time that also felt that keeping the separation made sense, so I left it the way that it was.

Why two URIs?

The other question one might ask “Why are there two base URIs, /contacts and /contact?” That’s a reasonable question.

Context, from an HTTP perspective, a URI is just an identifier, it can be anything. It doesn’t have to even make sense to the client, but there is nothing wrong if it does. For example, have you looked at your average MSDN page lately? I’ll bet your not going to memorize those URIs any time soon. Try this one on for size: http://msdn.microsoft.com/en-us/magazine/cc135976.aspx.

The first reason, is well because I could. Although it is very common to have base URIs for items and collections be the same, nothing forces you to do that because again it’s just an identifier. Speaking to various folks I found some preferred that it not be while many others thought it MUST be the same . In order to break that mental mold I chose to keep them separate.

The second reason was to illustrate how to keep the client decoupled from the server by leveraging some of what HTTP has to offer. By the conventional wisdom / using a single base URI, the client posts to “/contacts” and gets back a response which contains the new ContactID. The client then has logic to retrieve that ID and to append it to the base URI i.e. “/contacts/1” to get that contact. That however is flawed and won’t work in the ContactManager sample as the item is at a different base URI ;-)

It’s not an issue though because fortunately HTTP provides an answer for us, the location header. If we put on our pedantic hats and head on over to the HTTP RFC we see the following:

“For 201 (Created) responses, the Location is that of the new resource which was created by the request.”.

201 is the status code returned from POST whenever a resource is created. When the server creates a resource it can also include a Location header indicating the URI where that new resource is located. For example if I post to “/contacts” the server can return me a location header of “/contact/1” to tell me where to find it.

It doesn’t have to have an ID in the URI though! It could be the name “/contact/glenn%20block”. It could be a guid i.e. “/contact/849bb2ff-ccff-4315-b2ea-4dcb9736b394”. It is completely up to the server and the contents of the URI may not even appear in the contact response itself. It doesn’t matter though. As long as my client is pedantic :-) and follows the RFC all it has to do is save the location header URI and it can find that resource.

The beauty of this is that the server can evolve over time how it creates those URIs and the client is not broken. Oh no you are probably saying, here come the REST zealots!

Hardly. For example (kudos to @howard_dierking for this scenario) imagine initially when we created our system we used long IDs in the URI that point to each contact. Then over time we realize we need to scale out and replicate across servers. At that point we need an ID that is unique across all DB instances, such as a GUID. We can now silently change the contact URI to use a GUID instead. Our clients happily operate without a hitch as they simply take the newer URI that is handed to them in the location header.

I hope this clarifies why we have 2 controllers which itself has nothing to do with REST.

This entry was posted in ASP.NET Web API. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • JordanM

    This “problem” is caused by the use of the name “Controller” in WebAPI. Its a terrible choice of name. One of the main benefits of design patterns is that developers understand the basic concept as soon as they see a familiar name. A “Controller” in web api has nothing whatsoever to do with MVC, so it shouldn’t be called a controller.

    A better name would be “Resource”, or “ResourceService” or something similar.

  • http://blogs.msdn.com/gblock Glenn Block

    That’s a good point Doug.

  • http://www.facebook.com/doug.moscrop Doug Moscrop

    But this wouldn’t eliminate the second controller. I don’t oppose what you suggest – but the /contacts/ resource comes right back as soon as you want to search for contacts by first name..

  • http://www.facebook.com/doug.moscrop Doug Moscrop

    Not to mention that, without first going to the contact collection, how would anyone have discovered a contact? A bookmark later on, sure, but not without first going through the contacts resource. There’s absolutely nothing to gain by combining them together, and nothing to lose by separating them. You said “a list of resources is semantically separate from  a resource” – perhaps you should have just said “A list of things is different than a single thing”, because the ‘resource’ part of it is irrelevant.

  • http://johnvpetersen.myopenid.com/ John V. Petersen

     Exactly…it’s an architectural style.  There are numerous ways to implement.  There needs to be some constraints. For if there were none, it would be unbounded and undefinable. To paraphrase the late Justice Potter Stewart in Jacobellis v. Ohio (1964) – ” I shall not today attempt further to define the kinds of material I understand to be embraced within that shorthand description ["REST"]; and perhaps I could never succeed in intelligibly doing so. But I know it when I see it”

  • http://twitter.com/aliostad Ali

    URI aesthetics has nothing to do with REST.

    As you have said, and as far as my understanding with REST goes, URI needs to be unique not necessarily readable. It identifies a resource. It is for the consumption of machines not humans. It does not matter if it is /Products/1 or /Products?id=1. It does NOT care.

    It is a good practice to make it human-readable – this will help with search engine optimisation – which obviously has nothing to do with REST.

  • http://muddypa.ws nportelli

    Ha and disqus even closed my sarcasm tag for me!  Awesome.

  • http://muddypa.ws nportelli

    Not when I posted the comment.  More in reference to people not having comments on what they call a blog. I forgot my tag.

  • http://twitter.com/gblock Glenn Block

    is that bad? I do have some decent spam controls in place.

  • http://twitter.com/gblock Glenn Block

    REST is an architectural style, but the point is it does not dictate how the application itself is implemented. It does bring a set of constraints, but the code used to satisfy those constraints is completely orthagonal.

  • http://johnvpetersen.myopenid.com/ John V. Petersen

     Hi Rob..

    If REST is not about architecture, then what is it about? IMHO, I think REST has been  made to appear more  complicated than what it really is. Then again, maybe I’m being overly simplistic!!

  • http://blogs.msdn.com/gblock Glenn Block

    Hmm, that separation is there but we differ on the proper separation. The vector is a bit different than you described. The semantics of a collection resource is you POST to it in order to create a new resource and you get a 201 status. The contact doesn’t exist yet, it is created as a result of the POST to the contacts resource.

  • http://profiles.google.com/jnobile John Nobile

    Irony of ironies: the ubiquity of “REST” in this post and comment thread will ensure it shows up for anyone who wants to learn about REST. And now I am making it worse.

    On topic, I do take issue with the arbitrary, but not complete separation of the controllers.

    Complete separation would put creation, modification and deletion of individual resources on the singular route (/contact) and creation, modification (adding/removing items) and deletion of a collection on the plural route (/contacts). Just like objects and collections in code, the separate routes then truly embody the difference.

    However, this sample mingles the creation of single items into the plural route while updating and deleting single resources is over on the singular route.

    For a simple controller, I see no reason to confuse the API with this separation. Especially since the separation is not complete.

  • http://muddypa.ws nportelli

    Gasp, you have comments on your blog?!

  • http://blogs.msdn.com/gblock Glenn Block

    Hi Thor

    REST/HTTP has nothing to say about how how a resource is handled behind the scenes. 
    That may be according to their wisdom and you are free to accept it. I don’t.

  • Thor A. Johansen

    In the thread http://bit.ly/zzSXA1, Rickard Öberg and others make a good case arguing that REST resources should be aligned with your use cases (and not your entities/aggregates).

    So according to their wisdom, the argument of whether to use two controllers, one for the entities and one for collections of entities is really moot.

  • http://blogs.msdn.com/gblock Glenn Block

    HI Darren

    ContactController is here:http://code.msdn.microsoft.com/Contact-Manager-Web-API-0e8e373d/sourcecode?fileId=49595&pathId=1874221832

    ContactsController is here: http://code.msdn.microsoft.com/Contact-Manager-Web-API-0e8e373d/sourcecode?fileId=49595&pathId=1919346874

    I agree they look the same. It would be very easy to rename ContactsController to ContactsCollectionController

    Yes they look the same, but they are semantically different. The handling for an item is different than the handling for a collection. They address separate concerns.

    1. POST to the collection means create a child resource. POST to the item resource in this example has no meaning.

    2. DELETE to the item means remove the item. DELETE to the collection, could mean to clear out the collection or could mean nothing.

    In either case these are clear examples of where one resource handles an http method one way while the other handles it differently.

    In either case my point in this post is that this whole discussion is not about REST or NOT or HTTP or NOT. It’s a design decision. I can be wrong and that’s fine, wrong does not mean RESTful or not RESTful.

  • http://blogs.msdn.com/gblock Glenn Block

    @darren

    ContactsController is here: http://code.msdn.microsoft.com/Contact-Manager-Web-API-0e8e373d/sourcecode?fileId=49595&pathId=1919346874

    ContactController is here: http://code.msdn.microsoft.com/Contact-Manager-Web-API-0e8e373d/sourcecode?fileId=49595&pathId=1874221832

    It has nothing to do with academic, it has to do with concerns. One handles a collection and the other handles a single resource. For example, when I post to a collection I expect the item is going to be added as a child resource which is specific to the collection resource.

    Ont the item side, I need to handle DELETE for the item resource. That probably doesn’t make sense when I send a DELETE to the collection. It could if I want to implement clearing the collection when it receives a DELETE.

    Two examples of how the handling of an item differs from the handling of a collection. We do the same in code when we handle domain models. I usually will have a Collection type and an Item type they are not one and the same.

    Again all that being said, the sky won’t fall down if you combine them and YMMV. My point is the point of debate is around a design decision and not something dictated in any way by REST or HTTP.

    Thanks

  • http://twitter.com/KaminskiRay Ray Kaminski

    pedantic, I find some many reasons to use that word these days.

  • Anonymous

    Can you provide a link to the code (say, a Github or Codeplex page) for ContactsController and ContactController?

    I can understand wanting to separate concerns, but you’re also adding in some difficulty for others in that:

    ContactsController and
    ContactController

    … look remarkably the same, to the point of confusion I think.  That little “s” is hard to read.  

    If there’s some complex stuff going on in the controllers  with different dependencies required for each, I might understand making this trade-off (hopefully not).  But if each controller has a couple simple actions, all wired to the same database “context” object or repository, then separating them seems a little academic.

  • http://twitter.com/RobAshton Rob Ashton

    I tend to do one class per handler and know nothing about REST (because all you pedants scared me away ;-))

  • http://blogs.msdn.com/gblock Glenn Block

    Hi Colin

    There’s nothing wrong with doing what you propose. Both approaches are completely valid and YMMV.

  • Colin Bull

    Thanks for the post, I to was wondering why there are two controllers in the example.. And after reading this post I have to say, I can the merits of either approach. 

    One thing I would say is though (and I no I don’t want to turn this into a REST argument ;) ) with the dual controller example we have

    GET /contact/1

    PUT /contact/1

    but then we have

    POST /contacts/

    Now I see POST and GET as duals  in this scenario so I would prefer to see 

    POST /contact/ 

    and not have it split over two controllers, after all it can still return the new resource in the location header, as you say above, and I think this is more intentional as you are actually posting a single contact.

    I understand that there is the argument that post actually has no effect on a single contact resource but only effects the collection contact resource, but I think this URL schema is more discoverable, well in my head anyway. 

  • http://blogs.msdn.com/gblock Glenn Block

    OK, I thought you had asked that. I’ll go update the post.

  • http://blogs.msdn.com/gblock Glenn Block

    Hi Rob

    Well I wrote the original one which was before we merged with MVC. Once the merger happened it was ported from services to controllers.

    I think we clearly have different definitions of REST so I will say that my arguments are based on my understanding which doesn’t necessarily match yours :-)

    Separation of concerns is a general term that applies to software. Item resource vs Collection resource is a conceptual thing, one returns a single item and the other returns a collection. So because of that it makes sense (to me) to separate them rather than mix them. No REST was used in this explanation.

    I can only dispute your last point based on my understanding of REST. In that understanding the arguments I used have nothing to do with REST.

    Cheers

  • http://blog.wekeroad.com robconery

    Oh, I should add that I didn’t ask why there are 2 URI stubs. I know that much :). All I asked was why you need 2 controllers for the same Model.

  • http://blog.wekeroad.com robconery

    Thanks for the post Glenn… I didn’t know it was you who wrote that sample :) so your patience is… Quite lovely.

    That said… One thing we agree on is that REST doesn’t have anything to do with Controllers and architecture… Yet you state “separation of concerns” and how an item resource is different than a collection resource. What concerns are you separating here? To me… These are RESTful concerns.

    But you end with “it has nothing to do with REST” which is confusing because the prior post, in it’s entirety, uses RESTful ideas to defend why there are two Controllers.