Obsługa błędów jQuery Ajax, wyświetla niestandardowe komunikaty wyjątków

727

Czy jest jakiś sposób, aby wyświetlić niestandardowe komunikaty wyjątków jako ostrzeżenia w komunikacie o błędzie AJAX jQuery?

Na przykład, jeśli chcę wyjątek po stronie serwera poprzez poprzeczne przez throw new ApplicationException("User name already exists");, chcę złapać ten komunikat ( „nazwa użytkownika już istnieje”) w komunikacie o błędzie 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);
      }
    });
  }
});

Przy drugim alercie, w którym ostrzegam o zgłoszonym błędzie, otrzymuję, undefineda kod stanu to 500.

Nie jestem pewien, gdzie się mylę. Co mogę zrobić, aby rozwiązać ten problem?

Roman C.
źródło

Odpowiedzi:

357

Upewnij się, że ustawiłeś Response.StatusCodecoś innego niż 200. Napisz wiadomość wyjątku za pomocą Response.Write, a następnie użyj ...

xhr.responseText

..w twoim javascript.

Sprintstar
źródło
9
Jest to nadal poprawny sposób na zrobienie tego po 2 i pół roku ... :) Poszedłem trochę dalej i faktycznie zwróciłem własny obiekt błędu JSON, który może obsłużyć pojedynczy lub wiele błędów, całkiem dobry do sprawdzania poprawności formularza po stronie serwera.
AlexCode
@Wilson Było tak, jak pokazano w innych wysoko ocenianych odpowiedziach tutaj.
Sprintstar
3
Jestem teraz w 2014 roku. JSON zdominował erę. Więc używam xhr.responseJSON. : D
Ravi,
5
xhr.responseJSON jest ustawiany tylko wtedy, gdy upewnisz się, że ustawiony jest meta typ (np. „Content-type: application / json”). Właśnie ten problem napotkałem; tekst odpowiedzi został ustawiony - odpowiedź JSON nie.
Igor
217

Kontroler:

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

Wyświetl skrypt:

$.ajax({
    type: "post", url: "/SomeController/SomeAction",
    success: function (data, text) {
        //...
    },
    error: function (request, status, error) {
        alert(request.responseText);
    }
});
AlexMAS
źródło
13
To nie jest „poprawna” odpowiedź na pytanie, ale z pewnością pokazuje rozwiązanie problemu na wyższym poziomie ... Fajnie!
Ryan Anderson
3
Robię coś podobnego. Działa dobrze, jeśli wszystko jest zrobione na polu programowania. Jeśli spróbuję połączyć się z innego urządzenia w sieci, xhr.responseText zawiera ogólny błąd strony HTML, a nie mój niestandardowy komunikat, zobacz stackoverflow.com/questions/3882752/...
jamiebarrow
6
Uważam, że powinieneś również dodać odpowiedź. Stan = kod 500; linia do metody OnException.
Alexander Prokofyev
4
Dostosowałem to - ponieważ chciałem otrzymać kod statusu 500, ale aby mieć opis wyjątku w opisie statusu (zamiast „Wewnętrzny błąd serwera”) - response.StatusCode = (int)HttpStatusCode.InternalServerError;iresponse.StatusDescription = filterContext.Exception.Message;
Kram
4
Jeśli używasz IIS7 lub nowszej wersji, może być konieczne dodanie: response.TrySkipIisCustomErrors = true;
James Gaunt
97

Po stronie serwera:

     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

           }
 }

Strona klienta:

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

Ogólna obsługa błędów Ajax

Jeśli muszę zrobić ogólną obsługę błędów dla wszystkich żądań ajax. Ustawię moduł obsługi ajaxError i wyświetlę błąd na div o nazwie errorcontainer na górze zawartości 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);
                 });
Sanjeev Kumar Dangi
źródło
81

Musisz przekonwertować na responseTextJSON. Za pomocą JQuery:

jsonValue = jQuery.parseJSON( jqXHR.responseText );
console.log(jsonValue.Message);
Sydnej
źródło
5
+1, ponieważ jest to obecnie jedyna PRAWIDŁOWA odpowiedź na to pytanie! Możesz wywołać „jsonValue.Message”, aby otrzymać komunikat o wyjątku.
Kapitan Rozsądny
2
W rzeczywistości nie jest to poprawna odpowiedź, ponieważ pytanie nie dotyczy JSON, a przykładowe żądanie konkretnie pyta o HTML jako odpowiedź.
SingleShot,
+1 poprawnie. Uwaga: Często zdarza się, że obiekt zakodowany w JSON jest wysyłany przez jqXHR.responseText (ciąg znaków). Następnie możesz użyć obiektu jsonValue zgodnie z potrzebami. Użyj konsoli Firebug, aby przejrzeć odpowiedź za pomocą console.log (jsonValue).
jjwdesign
To daje mi „Uncaught SyntaxError: Nieoczekiwany numer”
Ben Racicot
1
Analizowany obiekt JSON jest udostępniany przez właściwość responseJSON obiektu jqXHR. Dlatego nie ma potrzeby analizowania właściwości responseText. Możesz po prostu zrobić: console.log (jqXHR.responseJSON.Message)
Eric D'Souza
37

Wywołanie asp.net spowoduje zwrócenie tytułu komunikatu o błędzie:

Sam nie napisałem całego formatuErrorMessage, ale uważam, że jest bardzo przydatny.

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) ); 
})
Sam Jones
źródło
22

Tak właśnie zrobiłem i działa do tej pory w aplikacji MVC 5.

Typem zwrotu kontrolera jest 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"};
}

A po stronie klienta tak wygląda funkcja 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;
    }
});
Cengiz Araz
źródło
20

Jeśli ktoś jest tutaj, jak w 2016 r. W celu uzyskania odpowiedzi, użyj .fail()do obsługi błędów, ponieważ .error()jest przestarzały od jQuery 3.0

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

Mam nadzieję, że to pomoże

Uczeń
źródło
2
jqXHR.error()jest przestarzały (faktycznie usunięty) w jQuery 3.0, ale o ile wiem, wywołania zwrotne errori nie są przestarzałe. success$.ajax()
Neil Conway,
16

Rozwiązanie ogólne / wielokrotnego użytku

Ta odpowiedź jest dostępna w przyszłości dla wszystkich, którzy napotkają ten problem. Rozwiązanie składa się z dwóch rzeczy:

  1. Wyjątek niestandardowy, ModelStateException który jest generowany, gdy sprawdzanie poprawności na serwerze nie powiedzie się (stan modelu zgłasza błędy sprawdzania poprawności, gdy używamy adnotacji danych i parametrów działania kontrolera o silnym typie)
  2. Filtr błędów działania kontrolera niestandardowego, HandleModelStateExceptionAttribute który przechwytuje niestandardowy wyjątek i zwraca stan błędu HTTP z błędem stanu modelu w treści

Zapewnia to optymalną infrastrukturę dla wywołań Ajax jQuery, aby wykorzystać ich pełny potencjał successi errorprocedury obsługi.

Kod po stronie klienta

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

Kod po stronie serwera

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

    // create new user because validation was successful
}

Cały problem jest szczegółowo opisany w tym poście na blogu, w którym można znaleźć cały kod do uruchomienia tego w aplikacji.

Robert Koritnik
źródło
14

Uznałem, że jest to miłe, ponieważ mogłem przeanalizować wiadomość wysyłaną z serwera i wyświetlić przyjazną wiadomość dla użytkownika bez stosu śledzenia ...

error: function (response) {
      var r = jQuery.parseJSON(response.responseText);
      alert("Message: " + r.Message);
      alert("StackTrace: " + r.StackTrace);
      alert("ExceptionType: " + r.ExceptionType);
}
crazyDiamond
źródło
11

 error:function (xhr, ajaxOptions, thrownError) {
        alert(xhr.status);
        alert(thrownError);
      }
w błędzie kodu prośby ajax o błąd łapania połączyć między klientem a serwerem, jeśli chcesz pokazać komunikat o błędzie aplikacji wysłać w zakresie sukcesu

Jak na przykład

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

}

Wara Haii
źródło
7

Jest to prawdopodobnie spowodowane brakiem cudzysłowów w nazwach pól JSON.

Zmień strukturę JSON z:

{welcome:"Welcome"}

do:

{"welcome":"Welcome"}
Chłopak
źródło
1
Nie powinno to mieć znaczenia, chyba że klucz jest zastrzeżonym słowem w JS. Nie widzę tu problemu.
John Gibb
1
JSON.stringify ({welcome: „Welcome”}) -> {„welcome”: „Welcome”}
Thulasiram
5

Uważam, że moduł obsługi odpowiedzi Ajax używa kodu stanu HTTP, aby sprawdzić, czy wystąpił błąd.

Jeśli więc po prostu rzucisz wyjątek Java na kod po stronie serwera, ale odpowiedź HTTP nie ma kodu statusu jQuery 500 (lub w tym przypadku prawdopodobnie obiekt XMLHttpRequest ) po prostu przyjmie, że wszystko jest w porządku.

Mówię to, ponieważ miałem podobny problem w programie ASP.NET, w którym zgłaszałem wyjątek ArgumentException („Nie wiem, co robić ...”), ale program obsługi błędów nie uruchamiał się.

Następnie ustawiłem na Response.StatusCode500 lub 200, niezależnie od tego, czy wystąpił błąd, czy nie.

Vitor Silva
źródło
5

Plik jQuery.parseJSON jest przydatny w przypadku powodzenia i błędów.

$.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); }
});
Nuri YILMAZ
źródło
5

Zgłoszono obiekt JSON wyjątku w obiekcie xhr. Po prostu użyj

alert(xhr.responseJSON.Message);

Obiekt JSON udostępnia dwie inne właściwości: „ExceptionType” i „StackTrace”

Edika
źródło
5

Ta funkcja generuje unikalne losowe klucze API, a jeśli nie, pojawi się wyskakujące okno dialogowe z komunikatem o błędzie

W widoku strony:

<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>

Z kontrolera:

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

Opcjonalny parametr wywołania zwrotnego określa funkcję wywołania zwrotnego, która ma być uruchomiona po zakończeniu metody load (). Funkcja oddzwaniania może mieć różne parametry:

Typ: Funkcja (jqXHR jqXHR, tekst StringStatus, String errorThrown)

Funkcja, która ma zostać wywołana, jeśli żądanie nie powiedzie się. Funkcja otrzymuje trzy argumenty: obiekt jqXHR (w jQuery 1.4.x, XMLHttpRequest), łańcuch opisujący typ błędu, który wystąpił, oraz opcjonalny obiekt wyjątku, jeśli taki wystąpił. Możliwe wartości drugiego argumentu (oprócz null) to „limit czasu”, „błąd”, „przerwanie” i „analiza składni”. Gdy wystąpi błąd HTTP, errorThrown otrzymuje tekstową część statusu HTTP, taką jak „Nie znaleziono” lub „Wewnętrzny błąd serwera”. Począwszy od jQuery 1.5, ustawienie błędu może akceptować tablicę funkcji. Każda funkcja będzie wywoływana kolejno. Uwaga: Ten moduł obsługi nie jest wywoływany dla skryptów między domenami i żądań JSONP między domenami.

Nɪsʜᴀɴᴛʜ ॐ
źródło
4
$("#save").click(function(){
    $("#save").ajaxError(function(event,xhr,settings,error){
        $(this).html{'error: ' (xhr ?xhr.status : '')+ ' ' + (error ? error:'unknown') + 'page: '+settings.url);
    });
});
ibrahim ozboluk
źródło
3

Rzuć nowy wyjątek na serwer, używając:

Response.StatusCode = 500

Response.StatusDescription = ex.Message ()

Wierzę, że StatusDescription jest zwracany do wywołania Ajax ...

Przykład:

        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
źródło
2

Chociaż minęło wiele lat, odkąd zadano to pytanie, wciąż nie znajduję xhr.responseTextodpowiedzi, której szukałem. Zwrócił mi ciąg znaków w następującym formacie:

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

których zdecydowanie nie chcę pokazywać użytkownikom. To, czego szukałem, jest jak poniżej:

alert(xhr.responseJSON.message);

xhr.responseJSON.message daje mi dokładną wiadomość z obiektu Json, którą można wyświetlić użytkownikom.

Saket
źródło
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
    });
});

Jeśli istnieje jakikolwiek formularz, należy go przesłać z potwierdzeniem

po prostu użyj reszty kodu

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

... ... });

Monzur
źródło
0

Najpierw musimy ustawić <serviceDebug includeExceptionDetailInFaults = "True" /> w pliku web.config:

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

Oprócz tego na poziomie jquery w części błędu należy przeanalizować odpowiedź na błąd, która zawiera wyjątek, taki jak:

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

Następnie za pomocą r.Message możesz faktycznie wyświetlić tekst wyjątku.

Sprawdź pełny kod: http://www.codegateway.com/2012/04/jquery-ajax-handle-exception-thrown-by.html

Avinash
źródło