0

So, my main question is in the title. How is it possible to avoid the browser to throw Http Statuscode 406 once an invalid method is supplied?

I've tried by default to allow all incoming methods by using [AcceptVerbs("GET", "POST", "PUT", "DELETE")] and after that to filter out the actual allowed method by using this method:

private bool CheckAllowedMethod(HttpMethod allowed, HttpMethod given)
{
    if (allowed == given)
    {
        return true;
    }

    throw new InvalidMethodException("This method is not available over " + Request.Method.Method);
}

Even though this works it isn't very neat. The behaviour I want to avoid when using [HttpPost], or any equivalent of those, is that the browser throws a Http Statuscode 406 and literaly prints nothing to the site even though I want to display a JSON string at all times.

So, is this possible any easier or do I have to use my current method?

Full code:

[AcceptVerbs("GET", "POST", "PUT", "DELETE")]
[Route("api/Auth/Login/{apikey}")]
public HttpResponseMessage GenerateLoginCode(string apikey = "") {
 HttpResponseMessage response = CreateResponse();

 try {
  CheckAllowedMethod(HttpMethod.Post, Request.Method);

  ChangeContent(response, JSONString.Create(Apikey.Login(apikey)));
 } catch (Exception ex) {
  ChangeContent(response, Error.Create(ex));
 }

 return response;
}

private HttpResponseMessage CreateResponse() {
 return Request.CreateResponse(HttpStatusCode.OK);
}

private void ChangeContent(HttpResponseMessage res, string data) {
 res.Content = new StringContent(data, System.Text.Encoding.UTF8, "application/json");
}

private bool CheckAllowedMethod(HttpMethod allowed, HttpMethod given) {
 if (allowed == given) {
  return true;
 }

 throw new InvalidMethodException("This method is not available over " + Request.Method.Method);
}
Thodor12
  • 149
  • 2
  • 2
  • 14
  • 1
    Do you wish to serve `406 Not Acceptable` or `405 Method Not Allowed`? (https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_Error) – Tomas Aschan Jul 16 '16 at 16:19
  • I actually wish to serve nothing but a 200 OK. If anything went wrong on the server side it just supplies a JSON string with the details of the error. However if I put [HttpPost] in front of the method and I try to access it via the browser (get) then it returns 406. – Thodor12 Jul 16 '16 at 16:22
  • 1
    See my answer for a way to accomplish this. I'd like to advice you to utilize the HTTP status codes, though, even if you *also* add some content in the body - that will make it much easier to consume your API. (I've spent some time recently consuming an API that responds with `200 OK` on every request, regardless of actual status, and then had error information in the body. Even though the API spec looks just as expressive as HTTP status codes to a human, it made the client code much more messy, since all available helper classes are built to cater for the HTTP protocol.) – Tomas Aschan Jul 16 '16 at 16:27

1 Answers1

2

I would not do this via accepting all methods and filtering manually, but rather with a middleware that catches the error response and rewrites it.

I dug quite deeply into error handling in Web API 2 earlier this year, and expanded on my findings in this blog post. If you do something similar to that, you could handle the exception from a disallowed method in a special catch clause in the middleware and write whatever you want to the response.

Community
  • 1
  • 1
Tomas Aschan
  • 58,548
  • 56
  • 243
  • 402