I've been going through this blog and I understand what he is saying, especially regarding the hierarchical structure (walking back along the path).
So
/objects/1/property
Removing property
should give you the object with id 1, and removing the id should give you all the objects. Excellent and logical.
But I always expose my data via view models, so,
/objects/list/1
will give me the object list view model of the object with id 1. Or /objects/detail/1
will give me the object detail view model for the object with id 1.
Using this approach I have ended up with a long structure just to get a specific view model! I.e. objects/visualization/analysis/thread
. Is this even restful? What I seem to be doing (subconsciously!) is structuring my restful API to match the namespace or module for where this specific view model lives (so in .NET it will be namespace: app.models.object.visualization.analysis).
How best to structure a restful endpoint like this? Is it better to have something like
objects-list/1
and objects-detail/1
?
Thanks.
Sorry, I should have been more clear. I will give a .NET example. Suppose I have a cart class
public class Cart
{
public int CardId { get; set; }
public string CartName { get; set; }
public DateTime Created { get; set; }
public DateTime LastUpdated { get; set; }
public IEnumerable<CartItem> Items { get; set; }
}
With a restful design, I could expose carts as /carts
, /carts/1
, /carts/1/items
and so on. But I always expose view models, not the actual data layer object. I.e.
public class CartListModel
{
public int CartId { get; set; }
public string CartName { get; set; }
}
and
public class CartViewModel
{
public int CartId { get; set; }
public string CartName { get; set; }
public DateTime LastUpdated { get; set; }
public IEnumerable<CartItemViewModel> Items { get; set; }
}
So this way I am only exposing the data that I actually need for a specific purpose. Now at the moment, I am exposing these view models as such /carts/list
or /carts/list/1
. Also /carts/view
and /carts/view/1
. So the original question is this restful? Do I infact need a separate endpoint for each view model? So /carts-list
and /carts-view
, carts-view/1
etc.
Don't really know what to put here! A view model is a representation of the object, only exposing certain properties necessary to bind to a view.
So suppose my object has the following JSON structure
{
id: 1,
name: 'Cart 1',
lastUpdated: '26-Sep-2014 16:51:23',
items: [
// an array of objects
]
}
For a certain view, like a simple table, I may only need the id and the name. So I expose a restful endpoint that gives me back the following structure
{
id: 1,
name: 'Cart 1'
}
Everything else is unnecessary. For a cart edit page, I will probably need a lot more data than just the id and name. The question is, how do I structure a restful endpoint to expose these different representations of the same object?
Resources are identified by URIs. The get the object with ID 1, do
GET /objects/1
To get a list of all objects, just
GET /objects
What representation of the object 1 is returned by the server is decided by content negotiation. This is done using HTTP headers, not URL path segments or query parameters. Do this:
GET /objects/1
Accept: appliction/vnd.com.example.object.detail+json
By this the client could request something you call the "detail view model".
If the client wants to get the "list view model", you could do
GET /objects/1
Accept: appliction/vnd.com.example.object.list+json
Note
Accept
headers have different values.Don't do any of these:
GET /objects/1/list
: This would request the sub resource called list
from object 1.GET /objects/1/list
: This would request another sub resource.GET /objects/1?model=detail
or GET /objects/1?model=list
: These are different URIs which identify different resources.