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

684

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

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

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

Теги:
custom-exceptions

20 ответов

308

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

xhr.responseText

.. в вашем javascript.

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

Контроллер:

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

Просмотр script:

$.ajax({
    type: "post", url: "/SomeController/SomeAction",
    success: function (data, text) {
        //...
    },
    error: function (request, status, error) {
        alert(request.responseText);
    }
});
  • 12
    Это не «правильный» ответ на вопрос, но он наверняка показывает решение проблемы на более высоком уровне ... Отлично!
  • 3
    Я делаю что-то подобное. Работает нормально, если все сделано на коробке разработки. Если я пытаюсь подключиться из другого блока в сети, xhr.responseText содержит общий html страницы с ошибкой, а не мое специальное сообщение, см. Stackoverflow.com/questions/3882752/…
Показать ещё 8 комментариев
91

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

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

jsonValue = jQuery.parseJSON( jqXHR.responseText );
console.log(jsonValue.Message);
  • 5
    +1 потому что на данный момент это единственный ПРАВИЛЬНЫЙ ответ на этот вопрос! Вы можете вызвать «jsonValue.Message», чтобы получить сообщение об исключении.
  • 2
    На самом деле это не правильный ответ, потому что вопрос не задает вопрос о JSON, а пример запроса специально запрашивает HTML в качестве ответа.
Показать ещё 3 комментария
34

При вызове 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) ); 
})
21

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

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

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

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

  • 1
    jqXHR.error() устарела (фактически удалена) в jQuery 3.0, но, насколько я знаю, обратные вызовы error и success $.ajax() для $.ajax() не устарели.
14

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

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

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

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

  • Пользовательское исключение ModelStateException, которое генерируется при завершении проверки на сервере (ошибки проверки состояния отчетов о состоянии штата, когда мы используем аннотации данных и используем сильные типизированные параметры действия контроллера)
  • Фильтр ошибок пользовательского контроля 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
}

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

7

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

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

{welcome:"Welcome"}

в

{"welcome":"Welcome"}
  • 1
    Это не должно иметь значения, если ключ не является зарезервированным словом в JS. Я не вижу в этом проблемы.
  • 1
    JSON.stringify ({welcome: "Welcome"}) -> {"welcome": "Welcome"}
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

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

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

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

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

4

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

такие как

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

}
4

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

alert(xhr.responseJSON.Message);

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

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
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({...

... ... });

0

Эта функция в основном генерирует уникальный случайный ключ 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), строка, описывающая тип возникшей ошибки и необязательный объект исключения, если это произошло. Возможные значения для второго аргумента (кроме нуля) - это "тайм-аут", "ошибка", "прервать" и "parsererror". При возникновении ошибки HTTP errorThrown получает текстовую часть статуса HTTP, например "Not Found" или "Internal Server Error". Начиная с jQuery 1.5, параметр ошибки может принимать массив функций. Каждая функция будет вызываться по очереди. Примечание. Этот обработчик не вызывается для междоменного скрипта и междоменных запросов JSONP.

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню