Overriding the HTTP Verb in ASP.NET MVC 2

Posted by Matthew Osborn on November 25, 2009

The Problem

Okay so lets start with a little bit of background on what a HTTP verb is. Raise your hand if you know what they are… Okay put it down people in your office are starting to stare at you. So without dragging out the explanation the HTTP verb is basically the way in which a request tells the server what it is trying to do. Most developers are familiar with the concept of a POST and GET request, however those are not the only types of HTTP verbs. There is also PUT, DELETE, and HEAD requests. Up until the advent of the “RESTful” buzz word the only verbs that ever really got used on a large scale were HEAD, GET, and POST. In fact most of the standard browsers can only issue those types of requests.

So what is the problem? We’ll some people out there (including some on ivory towers) like to have very thing be semantic. So if you have an action that deletes a row from the database the request should use the DELETE verb. Now we could argue the relevance of the need to follow this method but I don’t feel like it and its my blog post. If you remember what I said earlier about browsers you’ve probably already figured out the problem. That is right most browser can’t issue a DELETE request.

The Solution

The solution in ASP.NET MVC 2 is a rather small feature that was added to the framework as the result of the WCF team creating the REST Start Kit for MVC. That feature is the ability to override the HTTP verb in one of several ways so that the client, in this example the browser, is still issuing a POST request but the framework treats the request like the verb specified in the override.

There is three ways in which a developer can choose to override the HTTP verb and they all use the special cased key “x-http-method-override”. First, is to add a HTTP header to the request. This scenario is primarily for AJAX requests and in ASP.NET MVC 2 our AJAX helpers will add this header when need. The Second way is to add a hidden field to the form. The Last way is to use the query string to override the verb. The order of precedence works from the header version to the hidden field version to the query string version. If you are familiar with the way model biding works in ASP.NET MVC this is basically the same order of precedence. There is also some restrictions on what can be override. For instance a GET request cannot be overridden to anything else.

The Sample Code

HTTP Header

When you override the verb using the header method you need to add a http header with the special cased key “x-http-method-override” and the value of what you would like to override the verb to. When you use the AJAX helpers to issue a request this is done for you if you specify one of the verb types that needs to be overriden.

<% using(Ajax.BeginForm(new AjaxOptions(){HttpMethod=“Delete”})){ %> <input type=”submit” value=”Delete Using Http Header” /> <% } %>

Now if you look at the request you can see that there is an additional header added with the new value and ASP.NET MVC will treat that request as that verb type.

Hidden Input

This method is basically the same as the header method but instead of a header it is a hidden input with the name and value.

 <% using (Ajax.BeginForm(new AjaxOptions())){ %>
    <input type="hidden" name="x-http-method-override" value="Put" />
    <input type="submit" value="Put Using Hidden Field" />
<% } %>

Query String

Once again this works very similar to the other two methods. All you need to do is add the parameter “x-http-method-override” with the value of the desired override in the query string of URL that form will POST to. In this sample this is done using the overload to BeginForm that takes a RouteValue Collection because if the values are not used in the matching route they will get tacked on the URL in the query string.

<% using(Ajax.BeginForm("HttpVerbOverride", new RouteValueDictionary(), new AjaxOptions())){ %>
    <input type="submit" value="Delete using Query String" />
<% } %>

Summary

This is a pretty simple solution a problem that not all of you will face but I choose to write about it because it is one of the little know improvements we are making to version two of the framework. If you choose not to use this feature the only impact will be that “x-http-method-override” is now effectively a reserved/key word.