Обработка ошибок jQuery Ajax, показ пользовательских сообщений об исключениях

732

Есть ли какой-нибудь способ показать пользовательские сообщения об исключениях в качестве предупреждения в моем сообщении об ошибке jQuery AJAX?

Например, если я хочу создать исключение на стороне сервера через Struts by throw new ApplicationException("User name already exists");, я хочу перехватить это сообщение («имя пользователя уже существует») в сообщении об ошибке jQuery AJAX.

jQuery("#save").click(function () {
  if (jQuery('#form').jVal()) {
    jQuery.ajax({
      type: "POST",
      url: "saveuser.do",
      dataType: "html",
      data: "userId=" + encodeURIComponent(trim(document.forms[0].userId.value)),
      success: function (response) {
        jQuery("#usergrid").trigger("reloadGrid");
        clear();
        alert("Details saved successfully!!!");
      },
      error: function (xhr, ajaxOptions, thrownError) {
        alert(xhr.status);
        alert(thrownError);
      }
    });
  }
});

На втором оповещении, когда я предупреждаю о сгенерированной ошибке, я получаю, undefinedи код состояния равен 500.

Я не уверен, где я иду не так. Что я могу сделать, чтобы решить эту проблему?

Роман С
источник

Ответы:

359

Убедитесь, что вы установили Response.StatusCodeчто-то, отличное от 200. Напишите сообщение об исключении, используя Response.Write, затем используйте ...

xhr.responseText

... в вашем JavaScript.

Sprintstar
источник
9
Это все еще правильный способ сделать это после двух с половиной лет ... :) Я пошел немного дальше и фактически вернул свой собственный объект JSON с ошибкой, который может обрабатывать одну или несколько ошибок, что очень хорошо для проверки формы на стороне сервера.
AlexCode
@Wilson Это было так, как показано в других высоко оцененных ответах здесь.
Sprintstar
3
Сейчас я нахожусь в 2014 году. В эпоху доминирования JSON. Так что я использую xhr.responseJSON. : D
Рави
5
xhr.responseJSON устанавливается только в том случае, если вы уверены, что мета-тип установлен (например, «Content-type: application / json»). Это проблема, с которой я только что столкнулся; responseText был установлен - responseJSON не было.
Игорь
218

контроллер:

public class ClientErrorHandler : FilterAttribute, IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        var response = filterContext.RequestContext.HttpContext.Response;
        response.Write(filterContext.Exception.Message);
        response.ContentType = MediaTypeNames.Text.Plain;
        filterContext.ExceptionHandled = true;
    }
}

[ClientErrorHandler]
public class SomeController : Controller
{
    [HttpPost]
    public ActionResult SomeAction()
    {
        throw new Exception("Error message");
    }
}

Посмотреть скрипт:

$.ajax({
    type: "post", url: "/SomeController/SomeAction",
    success: function (data, text) {
        //...
    },
    error: function (request, status, error) {
        alert(request.responseText);
    }
});
AlexMAS
источник
13
Это не «правильный» ответ на вопрос, но он наверняка показывает решение проблемы на более высоком уровне ... Отлично!
Райан Андерсон
3
Я делаю что-то подобное. Работает нормально, если все сделано на коробке разработки. Если я пытаюсь подключением из другого окна на сеть, xhr.responseText содержит общую страницу ошибки HTML , а не мое собственное сообщение, см stackoverflow.com/questions/3882752/...
jamiebarrow
6
Я считаю, что вы также должны добавить response.StatusCode = 500; строка для метода OnException.
Александр Прокофьев
4
Я адаптировал это - так как я хотел 500 кодов статуса, но чтобы в описании статуса было сообщение об исключении (а не «Внутренняя ошибка сервера») - response.StatusCode = (int)HttpStatusCode.InternalServerError;иresponse.StatusDescription = filterContext.Exception.Message;
Крам
4
Если вы используете IIS7 или выше, вам может потребоваться добавить: response.TrySkipIisCustomErrors = true;
Джеймс Гонт
97

ServerSide:

     doPost(HttpServletRequest request, HttpServletResponse response){ 
            try{ //logic
            }catch(ApplicationException exception){ 
               response.setStatus(400);
               response.getWriter().write(exception.getMessage());
               //just added semicolon to end of line

           }
 }

Сторона клиента:

 jQuery.ajax({// just showing error property
           error: function(jqXHR,error, errorThrown) {  
               if(jqXHR.status&&jqXHR.status==400){
                    alert(jqXHR.responseText); 
               }else{
                   alert("Something went wrong");
               }
          }
    }); 

Обобщенная обработка ошибок Ajax

Если мне нужно сделать общую обработку ошибок для всех запросов AJAX. Я установлю обработчик ajaxError и выведу ошибку на div с именем errorcontainer в верхней части содержимого HTML.

$("div#errorcontainer")
    .ajaxError(
        function(e, x, settings, exception) {
            var message;
            var statusErrorMap = {
                '400' : "Server understood the request, but request content was invalid.",
                '401' : "Unauthorized access.",
                '403' : "Forbidden resource can't be accessed.",
                '500' : "Internal server error.",
                '503' : "Service unavailable."
            };
            if (x.status) {
                message =statusErrorMap[x.status];
                                if(!message){
                                      message="Unknown Error \n.";
                                  }
            }else if(exception=='parsererror'){
                message="Error.\nParsing JSON Request failed.";
            }else if(exception=='timeout'){
                message="Request Time out.";
            }else if(exception=='abort'){
                message="Request was aborted by the server";
            }else {
                message="Unknown Error \n.";
            }
            $(this).css("display","inline");
            $(this).html(message);
                 });
Санджив Кумар Данги
источник
82

Вам нужно конвертировать в responseTextJSON. Использование JQuery:

jsonValue = jQuery.parseJSON( jqXHR.responseText );
console.log(jsonValue.Message);
Сидней
источник
5
+1, потому что в настоящее время это единственный правильный ответ на этот вопрос! Вы можете вызвать «jsonValue.Message», чтобы получить сообщение об исключении.
Капитан Разумный
2
На самом деле это не правильный ответ, потому что вопрос не задает вопрос о JSON, а пример запроса специально запрашивает HTML в качестве ответа.
SingleShot
+1 Верно. Обратите внимание, что отправка объекта в кодировке JSON осуществляется через jqXHR.responseText (string). Затем вы можете использовать объект jsonValue так, как вам нужно. Используйте консоль Firebug для просмотра ответа с помощью console.log (jsonValue).
jjwdesign
Это дает мне «Uncaught SyntaxError: Неожиданное число»
Бен Racicot
1
Разобранный объект JSON становится доступным через свойство responseJSON объекта jqXHR. Поэтому нет необходимости анализировать свойство responseText. Вы можете просто сделать: console.log (jqXHR.responseJSON.Message)
Эрик Д'Суза
37

Если сделать вызов asp.net, это вернет заголовок сообщения об ошибке:

Я не написал все formatErrorMessage сам, но я нахожу это очень полезным.

function formatErrorMessage(jqXHR, exception) {

    if (jqXHR.status === 0) {
        return ('Not connected.\nPlease verify your network connection.');
    } else if (jqXHR.status == 404) {
        return ('The requested page not found. [404]');
    } else if (jqXHR.status == 500) {
        return ('Internal Server Error [500].');
    } else if (exception === 'parsererror') {
        return ('Requested JSON parse failed.');
    } else if (exception === 'timeout') {
        return ('Time out error.');
    } else if (exception === 'abort') {
        return ('Ajax request aborted.');
    } else {
        return ('Uncaught Error.\n' + jqXHR.responseText);
    }
}


var jqxhr = $.post(addresshere, function() {
  alert("success");
})
.done(function() { alert("second success"); })
.fail(function(xhr, err) { 

    var responseTitle= $(xhr.responseText).filter('title').get(0);
    alert($(responseTitle).text() + "\n" + formatErrorMessage(xhr, err) ); 
})
Сэм Джонс
источник
22

Это то, что я сделал, и это работает до сих пор в приложении MVC 5.

Тип возврата контроллера - ContentResult.

public ContentResult DoSomething()
{
    if(somethingIsTrue)
    {
        Response.StatusCode = 500 //Anything other than 2XX HTTP status codes should work
        Response.Write("My Message");
        return new ContentResult();
    }

    //Do something in here//
    string json = "whatever json goes here";

    return new ContentResult{Content = json, ContentType = "application/json"};
}

А на стороне клиента это выглядит как функция ajax

$.ajax({
    type: "POST",
    url: URL,
    data: DATA,
    dataType: "json",
    success: function (json) {
        //Do something with the returned json object.
    },
    error: function (xhr, status, errorThrown) {
        //Here the status code can be retrieved like;
        xhr.status;

        //The message added to Response object in Controller can be retrieved as following.
        xhr.responseText;
    }
});
Ченгиз Араз
источник
20

Если кто-то здесь, как в 2016 году для ответа, используйте .fail()для обработки ошибок, так как .error()устарела с jQuery 3.0

$.ajax( "example.php" )
  .done(function() {
    alert( "success" );
  })
  .fail(function(jqXHR, textStatus, errorThrown) {
    //handle error here
  })

Я надеюсь, что это помогает

ученик
источник
2
jqXHR.error()осуждается ( на самом деле удалены) в JQuery 3.0, но errorи successобратные вызовы $.ajax()не осуждается, насколько я знаю.
Нил Конуэй
16

Общее / многоразовое решение

Этот ответ предназначен для использования в будущем для всех тех, кто сталкивается с этой проблемой. Решение состоит из двух вещей:

  1. Пользовательское исключение ModelStateException которое возникает при сбое проверки на сервере (состояние модели сообщает об ошибках проверки, когда мы используем аннотации данных и строгие параметры действия контроллера)
  2. Пользовательский фильтр ошибок действий контроллера, HandleModelStateExceptionAttribute который перехватывает пользовательское исключение и возвращает статус ошибки HTTP с ошибкой состояния модели в теле

Это обеспечивает оптимальную инфраструктуру для вызовов jQuery Ajax для использования их полного потенциала с successиerror обработчиками обработчиками.

Код на стороне клиента

$.ajax({
    type: "POST",
    url: "some/url",
    success: function(data, status, xhr) {
        // handle success
    },
    error: function(xhr, status, error) {
        // handle error
    }
});

Серверный код

[HandleModelStateException]
public ActionResult Create(User user)
{
    if (!this.ModelState.IsValid)
    {
        throw new ModelStateException(this.ModelState);
    }

    // create new user because validation was successful
}

Вся проблема подробно описана в этом посте, где вы можете найти весь код для запуска этого приложения.

Роберт Коритник
источник
14

Я нашел это хорошим, потому что я мог разобрать сообщение, которое я отправлял с сервера, и показать дружественное сообщение пользователю без трассировки стека ...

error: function (response) {
      var r = jQuery.parseJSON(response.responseText);
      alert("Message: " + r.Message);
      alert("StackTrace: " + r.StackTrace);
      alert("ExceptionType: " + r.ExceptionType);
}
crazyDiamond
источник
12

 error:function (xhr, ajaxOptions, thrownError) {
        alert(xhr.status);
        alert(thrownError);
      }
в коде ошибки ajax запрос на ошибку перехвата соединиться между клиентом и сервером, если вы хотите, чтобы сообщение об ошибке вашего приложения отправлялось в области успеха

такие как

success: function(data){
   //   data is object  send  form server 
   //   property of data 
   //   status  type boolean 
   //   msg     type string
   //   result  type string
  if(data.status){ // true  not error 
         $('#api_text').val(data.result);
  }
  else 
  {
      $('#error_text').val(data.msg);
  }

}

Вара Хайи
источник
7

Вероятно, это вызвано тем, что имена полей JSON не имеют кавычек.

Измените структуру JSON с:

{welcome:"Welcome"}

чтобы:

{"welcome":"Welcome"}
парень
источник
1
Это не должно иметь значения, если ключ не является зарезервированным словом в JS. Я не вижу в этом проблемы.
Джон Гибб
1
JSON.stringify ({welcome: "Welcome"}) -> {"welcome": "Welcome"}
Туласирам
6

У вас есть объект JSON исключительной ситуации в объекте xhr. Просто используйте

alert(xhr.responseJSON.Message);

Объект JSON предоставляет два других свойства: «ExceptionType» и «StackTrace»

Эдика
источник
5

Я считаю, что обработчик ответов Ajax использует код состояния HTTP, чтобы проверить, не было ли ошибки.

Поэтому, если вы просто сгенерируете исключение Java в коде на стороне сервера, но в ответе HTTP нет кода состояния 500 jQuery (или в этом случае, вероятно, XMLHttpRequest объект ) просто предположит, что все в порядке.

Я говорю это, потому что у меня была похожая проблема в ASP.NET, где я генерировал что-то вроде ArgumentException («Не знаю, что делать ...»), но обработчик ошибок не срабатывал.

Затем я устанавливаю Response.StatusCode500 или 200 независимо от того, была ли у меня ошибка или нет.

Витор Сильва
источник
5

jQuery.parseJSON полезен для успеха и ошибки.

$.ajax({
    url: "controller/action",
    type: 'POST',
    success: function (data, textStatus, jqXHR) {
        var obj = jQuery.parseJSON(jqXHR.responseText);
        notify(data.toString());
        notify(textStatus.toString());
    },
    error: function (data, textStatus, jqXHR) { notify(textStatus); }
});
Нури Йилмаз
источник
5

Эта функция в основном генерирует уникальные случайные ключи API, и в случае, если это не так, появляется всплывающее диалоговое окно с сообщением об ошибке

На странице просмотра:

<div class="form-group required">
    <label class="col-sm-2 control-label" for="input-storename"><?php echo $entry_storename; ?></label>
    <div class="col-sm-6">
        <input type="text" class="apivalue"  id="api_text" readonly name="API" value="<?php echo strtoupper(substr(md5(rand().microtime()), 0, 12)); ?>" class="form-control" />                                                                    
        <button type="button" class="changeKey1" value="Refresh">Re-Generate</button>
    </div>
</div>

<script>
$(document).ready(function(){
    $('.changeKey1').click(function(){
          debugger;
        $.ajax({
                url  :"index.php?route=account/apiaccess/regenerate",
                type :'POST',
                dataType: "json",
                async:false,
                contentType: "application/json; charset=utf-8",
                success: function(data){
                  var result =  data.sync_id.toUpperCase();
                        if(result){
                          $('#api_text').val(result);
                        }
                  debugger;
                  },
                error: function(xhr, ajaxOptions, thrownError) {
                  alert(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
                }

        });
    });
  });
</script>

От контроллера:

public function regenerate(){
    $json = array();
    $api_key = substr(md5(rand(0,100).microtime()), 0, 12);
    $json['sync_id'] = $api_key; 
    $json['message'] = 'Successfully API Generated';
    $this->response->addHeader('Content-Type: application/json');
    $this->response->setOutput(json_encode($json));
}

Необязательный параметр обратного вызова указывает функцию обратного вызова, которая запускается после завершения метода load (). Функция обратного вызова может иметь разные параметры:

Тип: Функция (jqXHR jqXHR, String textStatus, String errorThrown)

Функция, вызываемая в случае сбоя запроса. Функция получает три аргумента: объект jqXHR (в jQuery 1.4.x, XMLHttpRequest), строка, описывающая тип возникшей ошибки и необязательный объект исключения, если таковой произошел. Возможные значения для второго аргумента (кроме нуля): «timeout», «error», «abort» и «parsererror». При возникновении ошибки HTTP errorThrown получает текстовую часть состояния HTTP, например «Не найдено» или «Внутренняя ошибка сервера». Начиная с jQuery 1.5, установка ошибки может принимать массив функций. Каждая функция будет вызываться по очереди. Примечание. Этот обработчик не вызывается для междоменных сценариев и междоменных запросов JSONP.

Nɪsʜᴀɴᴛʜ ॐ
источник
4
$("#save").click(function(){
    $("#save").ajaxError(function(event,xhr,settings,error){
        $(this).html{'error: ' (xhr ?xhr.status : '')+ ' ' + (error ? error:'unknown') + 'page: '+settings.url);
    });
});
Ибрагим Озболук
источник
3

Создайте новое исключение на сервере, используя:

Response.StatusCode = 500

Response.StatusDescription = ex.Message ()

Я считаю, что StatusDescription возвращается в вызов Ajax ...

Пример:

        Try

            Dim file As String = Request.QueryString("file")

            If String.IsNullOrEmpty(file) Then Throw New Exception("File does not exist")

            Dim sTmpFolder As String = "Temp\" & Session.SessionID.ToString()

            sTmpFolder = IO.Path.Combine(Request.PhysicalApplicationPath(), sTmpFolder)

            file = IO.Path.Combine(sTmpFolder, file)

            If IO.File.Exists(file) Then

                IO.File.Delete(file)

            End If

        Catch ex As Exception

            Response.StatusCode = 500

            Response.StatusDescription = ex.Message()

        End Try
Steffan
источник
2

Несмотря на то, что прошло много лет с тех пор, как этот вопрос был задан, я все еще не могу найти xhr.responseTextтот ответ, который искал. Он вернул мне строку в следующем формате:

"{"error":true,"message":"The user name or password is incorrect"}"

который я определенно не хочу показывать пользователям. Я искал что-то вроде ниже:

alert(xhr.responseJSON.message);

xhr.responseJSON.message дает мне точное сообщение от объекта Json, которое может быть показано пользователям.

Сакет
источник
1
$("#fmlogin").submit(function(){
   $("#fmlogin").ajaxError(function(event,xhr,settings,error){
       $("#loading").fadeOut('fast');       
       $("#showdata").fadeIn('slow');   
       $("#showdata").html('Error please, try again later or reload the Page. Reason: ' + xhr.status);
       setTimeout(function() {$("#showdata").fadeOut({"opacity":"0"})} , 5500 + 1000); // delays 1 sec after the previous one
    });
});

Если есть какая-либо форма, отправьте с подтверждением

просто используйте остальную часть кода

$("#fmlogin").validate({...

... ... });

Monzur
источник
0

Сначала нам нужно установить <serviceDebug includeExceptionDetailInFaults = "True" /> в web.config:

<serviceBehaviors> 
 <behavior name=""> 
  <serviceMetadata httpGetEnabled="true" /> 
    **<serviceDebug includeExceptionDetailInFaults="true" />** 
 </behavior> 
</serviceBehaviors>

В дополнение к этому на уровне jquery в части ошибки необходимо проанализировать ответ об ошибке, который содержит исключение, например:

.error(function (response, q, t) { 
  var r = jQuery.parseJSON(response.responseText); 
}); 

Затем, используя r.Message, вы можете фактически показать текст исключения.

Проверьте полный код: http://www.codegateway.com/2012/04/jquery-ajax-handle-exception-thrown-by.html

Авинаш
источник