Are your ASP.NET MVC URLs consistent?

Over the past couple of months, I’ve finally started work on my first web application built using the ASP.NET MVC framework. It’s going pretty well now, but at the start, in typical fashion, I spent more time googling and trawling message boards than actually cutting code.

My first head-scratching moment was around the naming of controllers and actions that form the path at the end of a URL. Specifically:

  • Are controller names plural or singular?
  • In a route, which comes first; the ID or the action?
  • Should I call this action add, create, insert or new?

Don’t laugh. This stuff will come as naturally as breathing to Rails developers — in fact, all of those decisions are already made for you if you use a tool like the scaffold generator to stub your code out. But with ASP.NET MVC, insufficient guidance over these sorts of choices leads to uncertainty, which leads to indecision, which leads to me mass-refactoring entire projects while I obsess over getting my object names perfect.

As you can imagine, this sort of thing is something I prefer to avoid. Luckily, some people far brighter and more experienced have already thought about this stuff, and have answers for all of my questions.

Are controller names plural or singular?

The ASP.NET MVC Framework uses a REST-based request model; instead of serving up files, it serves up resources. Resources are abstract concepts that together – like articles on Wikipedia or videos on Youtube – comprise an application’s content.

Such resources are stored in repositories, which are implemented in ASP.NET MVC as controllers.

Repository names are plural – they represent a collection of objects. For example, you might have a controller called Products. A Product – singular – is the type of resource it serves. It’s similar to the name you’d give an array or database table.

What order do I put the URL parameters?

I can’t find any reason why you’d want to deviate from the default here, although I did briefly try an OO-inspired controller/id/action route before I realised what was happening.

ASP.NET MVC is the same as Rails: first comes the controller name, then the action, then the ID of the resource in question:

Some people have suggested additional standard parameters you might like to put after this. One is pagination – if you split a list (e.g. search results) across several pages:

And another is alternative representation formats (e.g. RSS, XML, CSV etc):

If the output of your action can be represented in different formats, I think this a pretty neat way of specifying which one you want.

How do I name my controller actions?

This depends on what Route Handler you’re using. If you’re using Adam Tybor‘s Simply Restful Routing, then the decision is made for you – the action names are copied from Rails.

However, if you’re using the ASP.NET MVC default, you’ve got a bit more freedom. Stephen Walter, a product manager and ASP.NET MVC guru at Microsoft has come up with a series of standard controller action names. These are based loosely on the seven Rails controller actions, but exclude HTTP PUT and DELETE verbs, which aren’t supported by the default ASP.NET MVC route handler. They are as follows:

Controller Action HTTP verb Description
Detail GET Displays a single resource such as a database record.
Index GET Displays a collection of resources.
Create GET Displays a form for creating a new resource.
Insert POST Inserts a new resource into the repository.
Edit GET Displays a form for editing an existing resource.
Update POST Updates an existing resource.
Destroy GET Displays a page that confirms whether or not you want to delete a resource.
Delete POST Deletes a resource.

He also suggests some actions for non resource-based controllers – e.g. Home:

Controller Action HTTP verb Description
Login GET Displays a login form.
Authenticate POST Authenticates a user name and password.
Logout POST Logs out a user.

If you follow these guidelines, you will have a consistent and predictable URL format. Enforcing a standard URL format means less decision to make during development, and makes things clearer for end-users.

10 thoughts on “Are your ASP.NET MVC URLs consistent?

  1. Having the “delete” resource use GET is asking for trouble. It would be wiser to make a destructive action work via POST (as with any action that changes a resource).

  2. David: whoops, that was a mistake (now fixed). You’re dead right – all actions that submit changes to resources should be POSTs. Good spotting!

  3. It really is quite interesting to see ASP.NET only using GET and POST, when the HTTP spec has DELETE and PUT methods too.

    One of the examples in your post was:
    Delete – POST – Deletes a resource.

    If ASP.NET did things correctly, it would just be a HTTP DELETE which calls the delete action on the controller.

    Seems a bit backwards to do a HTTP POST to access delete method in a controller, when HTTP DELETE exists ;-)

  4. This is true.

    The way Rails gets around the lack of support in the HTML spec and browser support for those methods is to put a hidden field into the form to say this is a DELETE or PUT method. Admittedly a bit hackerish, but from the programmers point of view it’s completely transparent.

    As they say “optimised from programmer happiness” (provided you don’t look at the raw HTML :-D)

  5. Yeah. That’s how Simply Restful Routing does it as well. I guess it depends on the priorities of the project – do you want to use HTTP methods/REST to their full advantage, but use a little _method field hack to get them, or are you satisfied with using POST as a less specific “change something” method in conjunction with more controller actions?

  6. @David: “If ASP.NET did things correctly, it would just be a HTTP DELETE which calls the delete action on the controller.”
    Well, as you state yourself, the restriction to use HTTP POST to delete an item is really imposed by HTML, not ASP.NET. As you mention, Rails also just “gets around” it using hidden fields. If you wanted to delete using HTTP DELETE you’d need to use javascript. That’s not necessarily desired for all applications, so I guess that’s why neither ASP.NET nor Rails use the theoretically correct HTTP DELETE verb. Stephen Walter also wrote about this here:

Comments are closed.