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

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

Например, если я хочу вызвать исключение на стороне сервера через Стойки с помощью 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.

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

Как конвертировать HTML в PDF с помощью jsPDF
Как конвертировать HTML в PDF с помощью jsPDF
В этой статье мы рассмотрим, как конвертировать HTML в PDF с помощью jsPDF. Здесь мы узнаем, как конвертировать HTML в PDF с помощью javascript.
765
0
1 560 215
21

Ответы 21

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

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

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

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

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

xhr.responseText

..в вашем javascript.

Это все еще правильный способ сделать это через два с половиной года ... :) Я пошел немного дальше и фактически вернул свой собственный объект JSON с ошибкой, который может обрабатывать одну или несколько ошибок, что неплохо для проверки формы на стороне сервера.

AlexCode 19.07.2011 23:28

@Wilson Это было, как показано в других ответах с высоким рейтингом здесь.

Sprintstar 19.06.2014 17:21

Сейчас нахожусь в 2014 году. Эра доминирования JSON. Поэтому я использую xhr.responseJSON. : D

Ravi 18.12.2014 23:09

xhr.responseJSON устанавливается только в том случае, если вы гарантируете, что установлен мета-тип (например, «Content-type: application / json»). Я только что столкнулся с этой проблемой; responseText был установлен - responseJSON не был.

Igor 31.12.2014 02:55

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

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

Контроллер:

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);
    }
});

Это не «правильный» ответ на вопрос, но он, безусловно, показывает решение проблемы более высокого уровня ... Прекрасно!

Ryan Anderson 09.09.2010 01:21

Я делаю нечто подобное. Он отлично работает, если все сделано в окне разработки. Если я попытаюсь подключиться из другого ящика в сети, xhr.responseText будет содержать общую страницу ошибки html, а не мое собственное сообщение, см. stackoverflow.com/questions/3882752/…

jamiebarrow 07.10.2010 19:25

Я считаю, что вам также следует добавить строку response.StatusCode = 500; в метод OnException.

Alexander Prokofyev 27.04.2011 16:19

Я адаптировал это - поскольку мне нужен код состояния 500, но чтобы в описании состояния было сообщение об исключении (а не «Внутренняя ошибка сервера») - response.StatusCode = (int)HttpStatusCode.InternalServerError; и response.StatusDescription = filterContext.Exception.Message;

Kram 10.08.2011 15:28

Используя IIS7 и IOS (iPhone / iPad / iPod), я заставил его работать, используя приведенный выше сценарий и следующие строки: Responce.TrySkipIisCustomErrors = true; и response.StatusCode = (int) HttpStatusCode.InternalServerError;

Tuco 19.08.2011 01:33

@AlexanderProkofyev Для ответа уже задано значение 500, поскольку он выполняет метод OnException.

Chev 01.11.2011 19:37

В моем экземпляре ответ не установлен на 500 (я использую именно этот код), поэтому ошибка не обнаруживается на стороне клиента ....

The Coder 01.05.2012 03:13

Если вы используете IIS7 или выше, вам может потребоваться добавить: response.TrySkipIisCustomErrors = true;

James Gaunt 30.01.2013 22:37

мелкая придирка, но request в error: function (request, status, error) { на самом деле следует называть response. Аргументом является полученный вами отклик, а не созданный вами запрос.

MestreLion 01.03.2019 05:20

ИМХО, попытки поместить информацию в сообщения об ошибках - в значительной степени бесполезные усилия. В некоторых случаях это сработает, но прокси, брандмауэры и, возможно, даже защитники вредоносных программ, вероятно, удалят их. Кроме того, посредники могут возвращать клиенту ошибку 500, которая никогда не исходила от вашего сервера, поэтому ваш клиент вернет «undefined» или вызовет исключение или что-то еще для пользователя, потому что ошибка не такая, как ожидалось.

Ralph Bolton 26.11.2020 17:52

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

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

{welcome:"Welcome"}

к:

{"welcome":"Welcome"}

Это не имеет значения, если ключ не является зарезервированным словом в JS. Я не вижу здесь проблемы.

John Gibb 21.02.2011 04:42

JSON.stringify ({welcome: "Добро пожаловать"}) -> {"welcome": "Добро пожаловать"}

Thulasiram 20.10.2012 18:03

Вам необходимо преобразовать responseText в JSON. Используя JQuery:

jsonValue = jQuery.parseJSON( jqXHR.responseText );
console.info(jsonValue.Message);

+1 потому что на данный момент это единственный ПРАВИЛЬНЫЙ ответ на этот вопрос! Вы можете вызвать jsonValue.Message, чтобы получить сообщение об исключении.

Captain Sensible 29.04.2011 16:18

На самом деле это неправильный ответ, потому что вопрос не касается JSON, а пример запроса конкретно запрашивает HTML в качестве ответа.

SingleShot 20.07.2011 00:21

+1 Правильно. Обратите внимание: обычно объект в кодировке JSON отправляется через jqXHR.responseText (строка). Затем вы можете использовать объект jsonValue, как вам нужно. Используйте консоль Firebug, чтобы просмотреть ответ, используя console.info (jsonValue).

jjwdesign 10.06.2013 09:40

Это дает мне "Uncaught SyntaxError: Unexpected number"

Ben Racicot 24.05.2014 19:59

Анализируемый объект JSON становится доступным через свойство responseJSON объекта jqXHR. Таким образом, нет необходимости анализировать свойство responseText. Вы можете просто сделать: console.info (jqXHR.responseJSON.Message)

Eric D'Souza 08.09.2018 02:27

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

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

  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
}

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

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); }
});

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

error: function (response) {
      var r = jQuery.parseJSON(response.responseText);
      alert("Message: " + r.Message);
      alert("StackTrace: " + r.StackTrace);
      alert("ExceptionType: " + r.ExceptionType);
}

Серверная сторона:

     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);
                 });

Сначала нам нужно установить <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

При вызове 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) ); 
})
$("#save").click(function(){
    $("#save").ajaxError(function(event,xhr,settings,error){
        $(this).html{'error: ' (xhr ?xhr.status : '')+ ' ' + (error ? error:'unknown') + 'page: '+settings.url);
    });
});
$("#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({...

... ... });

Это то, что я сделал, и до сих пор это работает в приложении 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;
    }
});

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

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

которые я точно не хочу показывать пользователям. То, что я искал, выглядит примерно так:

alert(xhr.responseJSON.message);

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

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

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

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

jqXHR.error() устарел (фактически удален) в jQuery 3.0, но, насколько мне известно, обратные вызовы error и success для $.ajax() не являются устаревшими.
Neil Conway 02.09.2017 04:30

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

alert(xhr.responseJSON.Message);

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

Эта функция в основном генерирует уникальный случайный ключ 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 (). Функция обратного вызова может иметь разные параметры:

Type: Function( jqXHR jqXHR, String textStatus, String errorThrown )

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

 error:function (xhr, ajaxOptions, thrownError) {
        alert(xhr.status);
        alert(thrownError);
      }
in code error ajax request for catch error connect between client to server if you want show error message of your application send in success scope

такой как

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);
  }

}

В моем случае я просто удалил HTTP VERB из контроллера.

    **//[HttpPost]**   ---- just removed this verb
    public JsonResult CascadeDpGetProduct(long categoryId)
    {
       
        List<ProductModel> list = new List<ProductModel>();
        list = dp.DpProductBasedOnCategoryandQty(categoryId);
        return Json(new SelectList(list, "Value", "Text", JsonRequestBehavior.AllowGet));
    }

Другие вопросы по теме