2

Here is the code in my Controller Action:

[HttpPost]
public JsonResult MyAction()
{
    try
    {
        // Do something...

        return Json(new { Success = true });
    }
    catch(Exception ex)
    {
        return Json(new { Error = ex.Message });
    }
}

And, here is my script:

<script>
    $.ajax({
        type: "POST",
        url: '@Url.Action("MyAction", "MyController")',
        dataType: 'json'
    }).done(function (data) {
        alert(data.Success);
    }
    })
    .fail(function (data) {
        alert(data.Error);
    });
</script>

This works on success (the alert correctly shows "true"), but when the action fails, alert(data.Error) shows Undefined.

Using FireBug, I can see that the JSON data is correctly returned. Why is data.Error "Undefined" then?

UPDATE:

Here is the output from console.log(data):

readyState
4
responseText
"{"Error":"Attempted to divide by zero."}"
status
500
statusText
"Internal Server Error"
abort
function()
always
function()
complete
function()
done
function()
error
function()
fail
function()
getAllResponseHeaders
function()
getResponseHeader
function()
overrideMimeType
function()
pipe
function()
progress
function()
promise
function()
setRequestHeader
function()
state
function()
statusCode
function()
success
function()
then
function()

UPDATE 2:

Sorry, there was something wrong with my code (not the code here, but the code I was running). The correct output from console.log(data) is this:

Object {Error="Some error."}

ataravati
  • 8,891
  • 9
  • 57
  • 89

3 Answers3

5

Both responses from the server are successful json responses. As far as the client is concerned, nothing about the request has failed. Try this:

$.ajax({
    type: "POST",
    url: '@Url.Action("MyAction", "MyController")',
    dataType: 'json'
}).done(function (data) {
    if (data.Success) {
        alert('success!');
    } else {
        alert(data.Error);
    }
})
Jason P
  • 26,984
  • 3
  • 31
  • 45
  • That's not the problem. When there's an Exception, the `fail` event on the client side fires. I have tested that by using `alert('fail')` inside the fail block. – ataravati Jun 11 '14 at 18:46
  • In the code you posted, the exception is caught. It appears there's another exception occurring that isn't being handled. Do you have logging in place to debug? – Jason P Jun 11 '14 at 18:56
  • You were right. The fail event did not even fire, because the Exception was caught in the Controller. Thanks! – ataravati Jun 11 '14 at 19:23
2

I just faced a similar problem. Investigating the response in Developer tools, i see that even though the parameter data was passed as 'undefined' to the 'success' function call - the actual response body did contain the expected string.

The response can be deeper investigated in the developer tools -Network Tab -> press 'Start Capturing' - and on the actual request record - click on 'Go to detailed view').

The problem on my side resided in malformed Content-Type headers of the response. The response string was passed correctly, and was even correctly interpreted in other browsers (FF, Chrome, Safari). The headers set up on the server were, in this order:

  Response.AddHeader "Content-type", "text/html;charset=UTF-8"
  Response.AddHeader "Content-type","application/json"
  Response.ContentType = "application/json"

The result received by the client (investigated in network detailed view, like above mentioned) was:

Content-Type    text/html;charset=UTF-8,application/json

It seems that IE (8,9) is picky about the headers, specifically the Content-Type.

This lead in IE9, IE8 to the parameter data being passed as undefined and complete subsequent failure. As soon as i removed the unwanted headers, i.e. this line:

Response.AddHeader "Content-type", "text/html;charset=UTF-8"

The final conten-type received by the client was only:

Content-Type    application/json

And finally, the data parameter in this part of the ajax call was no longer "undefined", but the expected "object"

success: function(data, textStatus, XMLHttpRequest){
  alert(typeof(data));
},

* The server-side scripting language in this case is ASP's VBscript, you should know your corresponding syntax for the server-side header setting in order to know what to look for *

devplayer
  • 587
  • 4
  • 12
0

Looking at the jSON return, it appears that you should be looking for data.responseText.Error instead:

alert( data.responseText.Error );

UPDATE

Per the updated output, you're looking for the correct data but in the wrong call back. When you successfully handle exceptions on the server side you avoid having to deal will errors server-related errors on the client side.

As already pointed out, as far as your client-side code is concerned the request was successful and therefore you should be looking for data.Error in the done callback. Change your code to:

.done(function( data ) {
    !data.Success || alert( data.Success );
    !data.Error || alert( data.Error );
})
PeterKA
  • 24,158
  • 5
  • 26
  • 48