Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JQuery ajax call executes error on 200 [duplicate]

Tags:

jquery

c#

My c#/WebApi server code looks like:

[HttpPost]
public HttpResponseMessage Logout()
{
    // do some stuff here ... 
    return Request.CreateResponse(HttpStatusCode.OK);
}

In the client I do an ajax call using jquery 2.0.3

ADDED: Jquery code (typescript)...

    var ajaxSettings: JQueryAjaxSettings = {};
    ajaxSettings.type = 'POST';
    ajaxSettings.data = null;
    ajaxSettings.contentType = "application/json; charset=utf-8";
    ajaxSettings.dataType = "json";
    ajaxSettings.processData = false;

    ajaxSettings.success = (data: any, textStatus: string, jqXHR: JQueryXHR) => {
        console.log("Success: textStatus:" + textStatus + ", status= " + jqXHR.status);
    };
    ajaxSettings.error = (jqXHR: JQueryXHR, textStatus: string, errorThrow: string) => {
        console.log("Error: textStatus:" + textStatus + ", errorThrow = " + errorThrow);
    };

    $.ajax("http://apidev.someurl.com/v1/users/logout", ajaxSettings);

ADDED 2: Request headers resulting from the above code:

POST http://apidev.someurl.com/v1/users/logout HTTP/1.1
Host: apidev.someurl.com
Connection: keep-alive
Content-Length: 0
Cache-Control: no-cache
Pragma: no-cache
Origin: http://apidev.someurl.com
Authorization: SimpleToken 74D06A21-540A-4F31-A9D4-8F2387313998
X-Requested-With: XMLHttpRequest
Content-Type: application/json; charset=utf-8
Accept: application/json, text/javascript, */*; q=0.01
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36
Referer: http://apidev.someurl.com/test/runner/apitest/index.html?
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8

The response is 200, yet the error handler from the ajax call is fired instead of the success handler. Reason: parseerror, unexpected end of input.

One solution is to change serverside code to:

return Request.CreateResponse<String>(HttpStatusCode.OK, "Logout ok");

I understand that an empty response is not valid JSON, but the response message is intentionally empty. The 200 says it all. The response headers look like:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/7.5
Access-Control-Allow-Origin: http://apidev.someurl.com
Access-Control-Allow-Credentials: true
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Sun, 05 Jan 2014 01:20:30 GMT
Content-Length: 0

Is this a bug in jquery? Or should the Request.CreateResponse(OK) never be used that way? Should I fix this with some workaround in the client? AFAIK the server is not doing it wrong here ... any thoughts?

EDIT: Thanks to feedback of kevin, nick and John this issue has become clear. The solution I choose is to return a NoContent

return Request.CreateResponse(HttpStatusCode.NoContent);

Serverside this seems for this case the correct code. Clientside this is handled perfectly by JQuery (the succes handler is called). Thanx all for clearing this up!

(I don't know who to give credit for the answer ... since nick and kevin gave their valuable feedback in comments, johns feedback also added a better understanding) ... if no other suggestions are given ... i'll later mark the only 'answer' as the Answer)

Thanks all!

like image 658
Paul0515 Avatar asked Jan 05 '14 01:01

Paul0515


2 Answers

From MSDN, HttpStatusCode.OK is defined as follows (emphasis mine):

Equivalent to HTTP status 200. OK indicates that the request succeeded and that the requested information is in the response. This is the most common status code to receive.

Because a 200 implies some content is sent with the response (even an empty JSON object literal would be fine), you can run into problems if jQuery's Ajax implementation assumes a non-zero length response but does not receive it, especially if it tries parsing JSON (and possibly XML) from it. This is why John S makes the suggestion of changing the dataType to text; doing so would allow you to take specific action when receving an empty response.

On the other hand, HttpStatusCode.NoContent is defined as (emphasis mine):

Equivalent to HTTP status 204. NoContent indicates that the request has been successfully processed and that the response is intentionally blank.

In your particular situation, it may make more sense to set the status code to HttpStatusCode.NoContent to ensure that jQuery Ajax understands that it does not need to attempt any parsing/processing of the response.

like image 154
nick_w Avatar answered Nov 13 '22 09:11

nick_w


This is how jQuery works.

JQuery will assume the response is JSON if either:

  1. You specify dataType: 'json' in the ajax call, or
  2. You do not include the dataType setting but jQuery detects the response is JSON because of a response header.

And when jQuery assumes the response is JSON, it automatically tries to parse the response into objects before it calls the success handler. If the parse fails, the error handler is called instead.

From the jQuery documentation:

As of jQuery 1.9, an empty response is also rejected; the server should return a response of null or {} instead.

I don't know why jQuery couldn't make an exception for an empty response and treat it the same as null, or even as undefined, but if you cannot (or won't) change the response, a work-around would be to specify dataType: 'text' and then parse the response yourself.

$.ajax(url, {
    type: 'post',
    dataType: 'text',
    data: params,
    success: function(text) {
        if (text) {
            var data = jQuery.parseJSON(text);
            // ...
        }
    }
});
like image 20
John S Avatar answered Nov 13 '22 11:11

John S