4

I'm experimenting with ASP.Net Web API, which, by convention, splits controller methods into a Restful style of Get(), Put, Post and Delete. My question is how does one handle the PUT and DELETE requests that might come from a non-Ajax browser request.

So, let's say that I have foobar with id = 123. A normal fetch request would be

/foobars/123

To delete the item, the Restful way would be to issue:

DELETE /foobars/123

However, PUT and DELETE are not browser standards and do not have enough major browser support to be trusted if your request is coming from a non-Ajax browser request. So a common accepted workaround is:

POST /foobars/123?_method=DELETE (source: Restful Web Services)

For the new ASP.Net Web API, is there a best practice / common approach for working with this problem? What I want is for anything with a _method=DELETE to be routed to the DELETE() method in the controller and _method=PUT to be routed to the PUT() method of a controller.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
John
  • 3,332
  • 5
  • 33
  • 55

1 Answers1

3

You can easily achieve this using a DelegatingHandler.

So you would code:

public class HttpMethodHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var queryString = HttpUtility.ParseQueryString(request.RequestUri.Query);
        if(!string.IsNullOrEmpty(queryString["_method"]))
        {
            request.Method = new HttpMethod(queryString["_method"]);
        }
        return base.SendAsync(request, cancellationToken);
    }
}

And then add the handler to the pipeline. I have a blog on that.

Aliostad
  • 80,612
  • 21
  • 160
  • 208
  • Aliostad makes a good point. This should not be the accepted answer because it introduces a dangerous security vulnerability. Someone could send a (non-technical) user the link `"/delete/thing/23?_method=delete"` and they would unwittingly delete "thing 23" without ever making the choice to do so. The correct answer would be to use "Request.Form["_method"]", which would ensure the parameter can only be passed as a POST request rather than a GET queryparam. – Jansky Jul 08 '16 at 08:53