views:

87

answers:

3

Hi Guys,

If this is a duplicate, please let me know - because i had a quick look and couldn't find anything that really answers my question.

I'm experimenting with ASP.NET MVC 2. Now coming from a Web Forms background, i only really dealt with HTTP GET and HTTP POST.

I'm trying to see how i could apply GET/PUT/POST/DELETE to the respective CRUD operations on my repository (Find, Insert, Update, Remove).

Say i have a single controller, with the following action methods:

[HttpGet] // GET: /Products/{id}
[ActionName("Products")
public ActionResult Get(int id = 0) { ... }

[HttpPut] // PUT: /Products
[ActionName("Products")
public ActionResult Put(Product product) { ... }

[HttpPost] // POST: /Products/{product}
[ActionName("Products")
public ActionResult Post(Product product) { ... }

[HttpDelete] // DELETE: /Products/{product}
[ActionName("Products")
public ActionResult Delete(Product product) { .. }

Couple of questions on that - is that how you would name/separate the action methods? Should i be passing through the entire model (Product), or just the id?

The problem i'm having is i'm not sure how to handle invoking these action methods with the relevant HTTP Verb in my View.

At this stage, I'm thinking i would have 3 Views:

  1. "Index" - bind to IEnumerable<Product> model, listing all products, with "Edit", "Details" and "Delete" links
  2. "Single" - bind to single Product model, listing all details for a product, with an "Update" button.
  3. "New" - bind to single Product model, with form for creating product, with an "Create" button.

So - my question is, how do i specify i want to invoke a particular controller method with a specific HTTP Verb?

With Html.BeginForm, you can specify a FormMethod enumeration - but it only has GET and POST.

  • How can i perform a PUT and DELETE command?
  • Will i need a seperate View for each HTTP Verb?
  • If i have a link called "Delete", can i invoke a HTTP DELETE command to my controller, or does it need to be redirected to a new View with the form action delete?

Or, is this a silly/overkill design in the first place, should i just stick with "GET" and "POST"?

I'm (fairly) new to this style of web development (REST), so please be kind. :)

UPDATE

So i came across this interesting article from Stephen Walther, regarding this very topic.

He indicates a HTML Form only supports GET and POST (because i'm new to REST-style web development, i did not even know this, to which i am partially ashamed).

Apparently the only way to invoke a Controller action with PUT/DELETE is to do it with AJAX. Seriously?

So what should i do here, should i stick with GET/POST, or should i create a JavaScript file which wraps the underlying XmlHttpRequest code behind a nice function?

Which way are ASP.NET MVC developers leaning? Surely someone has asked themselves this same question.

+2  A: 

The reason that you're mostly familiar with GET and POST is because a regular old browser can only GET or POST a URL, especially when submitting a form.

Setting up your controllers this way, you're looking at something more along the lines of a REST API vs. a web site at least in spirit.

And yes, you are correct that only AJAX requests can set their request methods explicitly, so you're good to go if you'll be performing actions like deleting products via AJAX (in which case I would suggest only passing the ID since it is much lighter than serializing the entire product and you'll likely have easy access to the ID in your markup).

Here's the thing. If you are building a modern web application you're probably using AJAX and without getting too dogmatic you should expect your users to have JavaScript. If you want to do CRUD without AJAX then you can always POST a Product or use GET for a delete method with the ID in the URL (caveat to that, make sure the Delete method is protected behind authorization or a web crawler will gladly consume your GETs and delete all your data...)

If you don't want to build a REST API then don't sweat the fact that you're not using DELETE (just use GET with the ID in the URL) or you're not using PUT (just use POST with the product entity in the POST body).

REST is a great style for building APIs (no presentation tier, data sent in raw format to clients who consume them, could be a phone or a website, etc.) over HTTP. HTTP is great on its own for building web pages. Use what you need for what you need it for.

If you want to build a REST API to be used by both other people AND your web site, then do that, and just have your site's controller action methods call your API methods directly. I do that all the time. Use a web client like Hammock to make it easier on you.

Daniel Crenna
+1 for a) a good answer, and b) someone finally answering, hehe. only point id make is i'd rather do the DELETE with POST, not GET. REST principles dictate a GET should be able to be exeucted over and over again without changing "state". However, i'm probably leaning towards AJAX at this stage, because the website will have plenty of it anyway. Appreciate your answer.
RPM1984
@RPM1984 you are right, DELETE Must be done with POST, not GET.
eglasius
You should not do a GET for ANYTHING that modifies data. GET is simply retrieval. If your action involves the C, U, or D (Create, Update, or Delete), then you should invoke with a POST. Too many chances for data corruption if all it takes is a GET to change things.
andymeadows
@eglasius, @andymeadows - agree and agree. =).
RPM1984
I understand idempotence, like you mentioned, but GET and DELETE other than that specification detail, are identical. DELETE should also be idempotent. People sometimes get confused by the difference between idempotence and not changing state. What I mean is the first GET could delete the entity, the next GET to the same URL should return 404 or similar. That's why I said protect your GET with authorization. Same thing applies with DELETE. I see no real argument here to prefer POST over GET if GET is protected from web crawling. A DELETE is URL-based as well, so it can be "corrupted" as well.
Daniel Crenna
Also, check this out re: indempotence - http://stackoverflow.com/questions/741192/whats-the-correct-way-to-view-idempotency-in-terms-of-http-delete ... I won't spend too much time defending GET here, since why not use POST and avoid the possibility of human error, but it isn't as evil as most people claim.
Daniel Crenna
A: 

Personally I stick to as simple as possible full requests, instead of going AJAX all over. I use ajax, but in specific places where it enhances the experience (and I do with a progressive javascript approach).

Because of the above, I always just use GET and POST.

As for the naming, for those I'd do: Get, Update, Create, Delete, which makes it pretty clear. I actually use more like an action name that's related to what the operation does, but for simple things those work fine.

eglasius
RPM1984
A: 

HtmlHelper.HttpMethodOverride Method (System.Web.Mvc)

How about this?

takepara
Care to elobarate? (yes i have read the MSDN page). Have you used this in MVC? How? Anyway, now that i have discovered forms only support GET/POST (until HTML5 at least), i can't see how this would work.
RPM1984
<%= Html.HttpMethodOverride(HttpVerbs.Put) %><%= Html.HttpMethodOverride(HttpVerbs.Delete) %>
takepara
dude, first of all, don't put code in comments - edit your answer and put it there. Second of all, that's not an elaboration or an explanation of how that code could work (which is what this question is about). However, i'll do my own research on this method.
RPM1984