views:

597

answers:

4

The standard template for ASP.NET MVC (and MVC in general) seems to be {controller}/{action}/{id}, however, on a project i'm currently working on i'm not sure if that is an appropriate structure. If for example I had an application that controlled a car, to me it would make more sense to me to have the structure below:

  {car-rego}/{controller}/{action}/{data etc}

This makes sense to me because the car (identified by registration plate) is the resource we are performing operations on and the logical separation of functionality is seperated into the controller and action. This would result in URL's such as:

/ESX-121/Power/On
/ESX-121/Speed/Set/100
/ESX-121/Speed/Current -- get the current speed (could be /ESX-121/Speed also)
/ESX-121/Turn/Left
/ESX-121/Speed/Set/90
/ESX-121/Power/Off

If this followed the default pattern it would be something like below:

/Power/On/ESX-121
/Speed/Set/ESX-121/100
/Speed/Current/ESX-121 -- get the current speed (could be /Speed/ESX-121 also)
/Turn/Left/ESX-121
/Speed/Set/ESX-121/90
/Power/Off/ESX-121

To me the first option makes it much more sense as far as readable URL's go and the resource identifier is in a constant logical place. For example /Speed/Set/ESX-121/100 suggests to me that there is a resouce of type speed with an identifier of ESX-121 which is not really the case, the operation is on the car.

How do you go about structuring URL's and the related controllers and actions for cases such as this? Do you think this is an acceptable solution, or is there a better way for this to be structured?

+4  A: 

There is a big problem, from a "philosophical" point of view.

You seem to be using GET requests for pretty much everything, such as setting speed. The idea behind REST is that access to the ESX-121 resource gives you a representation of its current state, in your case its speed, its direction, if it's on etc.

POSTing some representation of the car at its URL will effectively change its current state. (If you are using XML for representation for example, you could post

<car><id>ESX-121</id><speed>100</speed><car>

to change its speed. Under ASP.net MVC you would POST a form for that.

What you are trying to do is to apply a SOAP service way of modeling (geared towards operations, or verbs) to a REST service, which is not really the idea.

It can be difficult to "get" the REST way of doing things, and it can go against everything you have been doing i you were using SOAP services, but it is important to keep those principles in mind.

In theory, you URL describes a resource, and the only operations available are carried out through GET (read), POST (create), PUT (create or update), DELETE (delete).

EDIT: Thanks to marxidad for correcting me on what each verb should map to.

Denis Troller
POST = ADD or APPEND. PUT = CREATE (if doesn't exist yet) or UPDATE (if already exists).
Mark Cidade
damn you're right ! Time to go to sleep.
Denis Troller
+2  A: 

Besides from the comments pointed out in the post above, I think it is perfectly ok to change the structure around a bit. (But not use GET for updating data as pointed out above)

Take for example a CMS, you'll often see the following structure:

{controller}/{id}/{action}
or
pages/about_the_company (the display action is the default action)
pages/about_the_company/edit (GET will display the edit page, while POST will perform an update)

Of course in a CMS the controller would be defaulted to pages so the url's would be even shorter.

Gidon
+1  A: 

REST is not about having clean URIs, it is about having the correct semantic attached to HTTP methods GET, POST, PUT and DELETE.

GET should only be for safe idempotent operations, POST should be for creation or processing, PUT should be for updating an existing resource and DELETE to (hmm) delete a resource.

You can use ugly URIs with lots of "? and &" parameters while still begin RESTful if you want.

Now about your URIs, while the second option may look fine, it is a way to write "plain english" using a language that is not english. It may sound a good idea in the first place, but the main idea behind making URIs readable is that the client can play with them and discover new features. That's why it is always a better idea to keep the tree structure of your site/application in your URIs.

See Jacob Nielsen's Alertbox about URL as UI for more information on the topic.

Vincent Robert
That's not REST at all. That's just proper usage of HTTP.
Wahnfrieden
A: 

If you define any kind of URI naming structure like "{car-rego}/{controller}/{action}/{data etc}" then your API is not REST. It is simply RPC. You cannot define URIs or URI naming conventions as part of a REST API - it directly violates one of the constraints of RESTful architecture.

See http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven for more information.

Wahnfrieden