This is going to be a web service that returns a JSON object. Currently, I'm using C# technology and simply using ASP.Net MVC to create the calls. This is not a web page, so SEO is not a concern.
I've come across a number of instances where I want to get the "next" or "previous" item in a list. For example, I've got a service that returns a featured photo. http://myservice.com/photos/123 which returns a JSON
{"name": "At_The_Concert", "id": "123", "src": "http://myservice.com/photostore/123.jpg"}
The client (Ajax, Mobile device, etc.) of this service wants to know what the "next" item is going to be. I’m struggling about what the url should be.
- http://myservice.com/photos/123/next
- http://myservice.com/photos/next/123
- http://myservice.com/nextphotos/123
or maybe the id property should just be a parameter
http://myservice.com/photos/next?photoId=123
Or maybe this is entirely wrong and it should be like
http://myservice.com/photos/?method=getNextPhoto&photoId=123
though with .Net's routing, it might be easier to write it as http://myservice.com/photos/method/getNextPhoto?photoId=123
I’m relatively new to web services and REST. I get the basic CRUD for REST, but I don’t know what is the best practice for creating more custom urls, in this case the "next" photo. Is there an accepted RESTful practice?
-
the last three are not RESTful they are RPC over HTTPuser7519– user751912/28/2011 21:39:12Commented Dec 28, 2011 at 21:39
-
That's interesting, because the 2nd to last (?method=) I based off Flickr's REST API.John– John12/29/2011 03:25:18Commented Dec 29, 2011 at 3:25
-
just because they call it REST doesn't mean they got it rightuser7519– user751912/29/2011 03:59:40Commented Dec 29, 2011 at 3:59
-
That is very true.John– John12/29/2011 13:02:04Commented Dec 29, 2011 at 13:02
3 Answers 3
Do it this way:
{"name": "At_The_Concert", "id": "123", "src": "http://myservice.com/photostore/123.jpg",
"next": "http://myservice.com/photos/345/",
"prev": "http://myservice.com/photos/901/"}
-
1+1 for the sane way to do it. Keeps the Prev/Next links 'clean' too.Dan McGrath– Dan McGrath12/28/2011 18:51:50Commented Dec 28, 2011 at 18:51
-
4A cool URL never changes. "myservice.com/photos/123/next" might point to different pictures depending on filter settings or user authorizations or day of week or phase of moon.S.Lott– S.Lott12/28/2011 18:54:23Commented Dec 28, 2011 at 18:54
-
But it does change. If I remove photos or add new photos, there will be a different "next" photo.John– John12/28/2011 19:22:38Commented Dec 28, 2011 at 19:22
-
3There will be a different value associated with "next" in the JSON reply. The URL for a given photo never changes. You don't want to have "myservice.com/photos/123/next" and ""myservice.com/photos/345" BOTH point to the same photo. You want "myservice.com/photos/345" to be the one, only and unchanging for photo 345. Since "myservice.com/photos/123/next" is always changing, you simply do not want to ever use it.S.Lott– S.Lott12/28/2011 19:39:44Commented Dec 28, 2011 at 19:39
-
I'm thinking that you're right. This was the original path that I went down. I was using a LinkedListNode<T> in the middle tier to generate the data. Everything was nice until I tried to serialize my LinkedListNode and . . . recursion blowup. /next seems like such a nice solution from the middle tier point of view, but alas, it does violate the Thou Shalt Have One Url And Only One Url Commandment.John– John12/28/2011 19:58:21Commented Dec 28, 2011 at 19:58
Having the next function be an operation server-side requires state information, particularly if you are involving filtering. This violates REST.
It seems more appropriate to provide a directory list at http://myservice.com/photos, and let the app call the appropriate http://myserivce.com/photos/id link when hitting next/previous. With this method, the filtering logic would be on the client, and it could be modified/reset without having to call the service again.
Alternatively, you could have request parameters into the http://myservice.com/photos that returns a filtered list. Naturally, this would require additional service calls if the filter changed, so you may wish to stick with the former suggestion.
The end result would be the same, however. Your state would reside where it should - in the client app as opposed to the server.
Another option is to look at OData and Service Operations it will guarantee RESTful style of your calls.