44

I'm trying to return an error message via Json from ASP.NET MVC controller. I want to display carriage returns on the screen, so the error will look like:

Error 1.
Error 2.

instead of "Error1.\u003cbr/\u003eErro2.\u003cbr.\u003e"

Here's my ASP.NET MVC code

Response.StatusCode = (int)HttpStatusCode.BadRequest;
string str = "Error 1.<br/>Error 2.<br.>";
return Json(str);

JavaScript (redacted):

.ajax({...
     error: function(xhr, textStatus, exceptionThrown) {
        $('#result').html(xhr.responseText);
     },

Debugging the xhr.responseText yields: ""Error1.\u003cbr/\u003eErro2.\u003cbr.\u003e""

Any ideas?

Hakan Fıstık
  • 16,800
  • 14
  • 110
  • 131
netwire
  • 7,108
  • 12
  • 52
  • 86

4 Answers4

81

would be nicer to return a list of errors and then build the html at the client.

Response.StatusCode = (int)HttpStatusCode.BadRequest;
List<string> errors = new List<string>();
//..some processing
errors.Add("Error 1");
//..some processing
errors.Add("Error 2");
return Json(errors);

and then at the client side

 .ajax({...
    error: function(xhr, textStatus, exceptionThrown) {
      var errorData = $.parseJSON(xhr.responseText);
      var errorMessages = [];
      //this ugly loop is because List<> is serialized to an object instead of an array
      for (var key in errorData)
      {
         errorMessages.push(errorData[key]);
      }
       $('#result').html(errorMessages.join("<br />"));
  },

you can also return a more specific error object and use a template solution, but this is the idea

Derek Greer
  • 15,454
  • 5
  • 45
  • 52
Avi Pinto
  • 4,266
  • 2
  • 24
  • 24
  • 1
    Are you sure that this would not return success? I usually do: return Json(new { success = false, errors = ... }); – Santhos Dec 08 '14 at 09:39
  • when you return httpCode 500, the error function will be called and not the success one. in your solution you have to check at every success function to see if you got an error. BTW' the Done/complete functions will be called no matter what httpCode you return – Avi Pinto Dec 08 '14 at 13:14
  • Returning HttpStatusCode.BadRequest does not work in our test environment but works in my dev environment. The ajax failure function is never hit. Any clues? – Bacon Dec 08 '16 at 03:01
  • Hi Jeff, this is strange, look at the DevTools, are you returning 400 from the server? maybe in your web.config someone placed an override for it returning a redirect to an error page to prevent user a way to see error pages(like the YSOD) any status code > 400 will be considered as an error at the client by jQuery – Avi Pinto Dec 08 '16 at 08:04
  • `using System.Net;` for `HttpStatusCode` – BurnsBA Dec 21 '16 at 19:50
14

If you are using JSON you probably don't want to embed HTML (that sort of defeats the purpose of returning a "data" object that you will format on the view.)

If you want to return HTML you could do this in your controller:

Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Content("Error 1.<br/>Error 2.<br/>"); 
Hector Correa
  • 26,290
  • 8
  • 57
  • 73
  • Returning HttpStatusCode doesn't work in our test environment but works on my dev machine. The ajax failure function is never hit. Any clues? – Bacon Dec 08 '16 at 03:03
5

It seems to me that you already made almost everything correct. The results which you have in the xhr.responseText is a JSON string. So you should insert only one additional call of the JSON.parse function

.ajax({...
    error: function(xhr, textStatus, exceptionThrown) {
        $('#result').html(JSON.parse(xhr.responseText));
    },

then the data like '"Error1.\u003cbr/\u003eErro2.\u003cbr.\u003e"' will be converted to the string 'Error 1.<br/>Error 2.<br/>'.

Inside of success event handler the ajax function call JSON.parse for you, but it do this not inside of the error handler. So converting the server response from JSON string you have to do manually.

Oleg
  • 220,925
  • 34
  • 403
  • 798
2

Yea, you're defeating the purpose like @Hector said..

And if you want to return true JSON, maybe try returning a Json(Dictionary<String, Object>) instead of a Json(string).

Bryan Migliorisi
  • 8,982
  • 4
  • 34
  • 47