JQuery AJAX and handling different data types

I am using ASP.Net MVC, but this applies to any framework.

I am making an Ajax call to my server which returns plain old HTML most of the time, however if there is an error, I would like it to return a JSON object with status (and a few other things). It seems that the way dataType

in the jQuery call is inappropriate to handle this well. By default, it seems to parse everything as html, resulting in padding <div>

"{ status: 'error', message: 'something bad happened'}"

.

[Edit] Ignoring the object dataType

and emitting the jQuery value doesn't work either. It treats the result type as string

and treats it as HTML.

One solution I came up with is trying to parse the result object as JSON. If it works, we know it as a JSON object. If it throws an exception, it's HTML:

$.ajax({
    data: {},
    success: function(data, textStatus) {
        try {
            var errorObj = JSON.parse(data);
            handleError(errorObj);
        } catch(ex) {
            $('#results').html(data);
        }
    },
    dataType: 'html', // sometimes it is 'json' :-/
    url: '/home/AjaxTest',
    type: 'POST'
});

      

However, using an Exception in this way strikes me as very bad design (and at least unintuitive). Is there a better way? I was thinking about wrapping the entire response in a JSON object, but in this case, I don't think that's an option.

Here is the solution I got from Steve Wilcock:

// ASP.NET MVC Action:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult AjaxTest(int magic) {
    try {
        var someVal = GetValue();
        return PartialView("DataPage", someVal);
    } catch (Exception ex) {
        this.HttpContext.Response.StatusCode = 500;
        return Json(new { status = "Error", message = ex.Message });
    }
}




// jQuery call:

$.ajax({
    data: {},
    success: function(data, textStatus) {
        $('#results').html(data);
    },
    error: function() {
        var errorObj = JSON.parse(XMLHttpRequest.responseText);
        handleError(errorObj);
    },
    dataType: 'html',
    url: '/home/AjaxTest',
    type: 'POST'
});

      

+10


a source to share


6 answers


For your JSON errors, you can return a 500 status code from the server instead of 200. The jquery client code can then use an error handler: $ .ajax to handle the errors. On a 500 response, you can parse the JSON error object from responseText, on a 200 response, you can just stub your HTML in the div as usual.



+9


a source


While Steve's idea is good, I'm adding this for completeness.

It looks like if you specify json datatype but return HTML jQuery will do just fine.

I tested this theory with the following code:

if($_GET['type'] == 'json') {
    header('Content-type: application/json');
    print '{"test":"hi"}';
    exit;
} else {
    header('Content-type: text/html');
    print '<html><body><b>Test</b></body></html>';
    exit;
}

      

$_GET['type']

- it's just so I can control what gets returned during testing. In your situation, you will return one or the other depending on whether everything was right or wrong. Past what's with this jQuery code:



$.ajax({
    url: 'php.php?type=html', // return HTML in this test
    dataType: 'json',
    success: function(d) {
        console.log(typeof d); // 'xml'
    }
});

      

Even though we specified JSON as dataType, jQuery (1.3.2) figures out that it is not.

$.ajax({
    url: 'php.php?type=json',
    dataType: 'json',
    success: function(d) {
        console.log(typeof d); // 'object'
    }
});

      

So you can take advantage of this (as far as I know) undocumented behavior to do what you want.

+6


a source


But why not just return JSON regardless of the status (success or error) in the POST and use GET to display the results?
Seems like the best approach if you ask me.

+3


a source


Or you can always return a JSON response and have one parameter as HTML content.

Sort of:

{
     "success" : true,
     "errormessage" : "",
     "html" : "<div>blah</div>",
}

      

I think you would need to escape the double quotes in the html value and the json parser will override that for you.

0


a source


I faced this same issue with MVC / Ajax / JQuery and wanted to use multiple data types (JSON and HTML). I have an AJAX request to use HTML dataType to return data, but I am trying to convert the data that is returned from an ajax request to a JSON object. I have a function like this which I call from my callback:

    _tryParseJson: function (data) {
        var jsonObject;

        try {
            jsonObject = jQuery.parseJSON(data);
        }
        catch (err) {
        }

        return jsonObject;
    }

      

Then I assume that if the jsonObject and errorMessage properties exist, an error has occurred, otherwise no error has occurred.

0


a source


I did it using only successful ajax callbacks and errors. This way I can have mixed strings and json object responses from the server.

Below I am ready to accept json, but if I get "parsererror" status (this means jquery has not been able to parse the incoming code as json since I expected), but it got "OK" (200) request status, then I I process the response as a string. Anything other than "parsererror" and "OK" I treat as an error.

$.ajax({
    dataType: 'json',
    url: '/ajax/test',
    success: function (resp) {
      // your response json object, see if status was set to error
      if (resp.status == 'error') {
        // log the detail error for the dev, and show the user a fail
        console.log(resp);
        $('#results').html('error occurred');
      }
      // you could handle other cases here
      // or use a switch statement on the status value
    },
    error: function(request, status, error) {
      // if json parse error and a 200 response, we expect this is our string
      if(status == "parsererror" && request.statusText == "OK") {
        $('#results').html(request.responseText);
      } else {
        // again an error, but now more detailed and not a parser error
        // and we'll log for dev and show the user a fail
        console.log(status + ": " + error.message);
        $('#results').html('error occurred');
      }
    }
  });

      

0


a source







All Articles