Gestione degli errori jQuery Ajax, mostra messaggi di eccezione personalizzati


729

Esiste un modo per mostrare messaggi di eccezione personalizzati come avviso nel mio messaggio di errore jQuery AJAX?

Ad esempio, se voglio lanciare un'eccezione sul lato server tramite Struts di throw new ApplicationException("User name already exists");, voglio catturare questo messaggio ("il nome utente esiste già") nel messaggio di errore 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);
      }
    });
  }
});

Al secondo avviso, dove avverto l'errore generato, visualizzo undefinedil codice di stato 500.

Non sono sicuro di dove stia andando male. Cosa posso fare per risolvere questo problema?

Risposte:


358

Assicurati di impostare Response.StatusCodequalcosa di diverso da 200. Scrivi il messaggio della tua eccezione utilizzando Response.Write, quindi usa ...

xhr.responseText

..in tuo javascript.


9
Questo è ancora il modo corretto di farlo dopo 2 anni e mezzo ... :) Sono andato un po 'oltre e in realtà restituisco il mio errore JSON oggetto in grado di gestire errori singoli o multipli, abbastanza buono per la convalida del modulo sul lato server.
AlexCode

@Wilson Era come mostrato nelle altre risposte di alto livello qui.
Sprintstar,

3
Sono ora nel 2014. Era dominata da JSON. Quindi io uso xhr.responseJSON. : D
Ravi,

5
xhr.responseJSON è impostato solo se si garantisce che sia impostato il meta-tipo (ad es. "Content-type: application / json"). Questo è un problema che ho appena riscontrato; responseText è stato impostato - responseJSON no.
Igor,

217

controller:

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

Visualizza script:

$.ajax({
    type: "post", url: "/SomeController/SomeAction",
    success: function (data, text) {
        //...
    },
    error: function (request, status, error) {
        alert(request.responseText);
    }
});

13
Questa non è una risposta "corretta" alla domanda, ma sicuramente mostra una soluzione di livello superiore al problema ... Bello!
Ryan Anderson,

3
Sto facendo qualcosa di simile. Funziona bene se tutto è fatto sulla scatola di sviluppo. Se provo il collegamento da una scatola diverso sulla rete, il xhr.responseText contiene la pagina di errore generico html e non il mio messaggio personalizzato, vedere stackoverflow.com/questions/3882752/...
jamiebarrow

6
Credo che dovresti anche aggiungere response.StatusCode = 500; linea al metodo OnException.
Alexander Prokofyev,

4
L'ho adattato - poiché volevo il codice statico 500, ma per avere il messaggio di eccezione nella descrizione dello stato (piuttosto che "Errore interno del server") - response.StatusCode = (int)HttpStatusCode.InternalServerError;eresponse.StatusDescription = filterContext.Exception.Message;
Kram

4
Se si utilizza IIS7 o versione successiva, potrebbe essere necessario aggiungere: response. TrySkipIisCustomErrors = true;
James Gaunt,

97

Lato server:

     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

           }
 }

Dalla parte del cliente:

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

Gestione generica degli errori Ajax

Se devo fare una gestione generica degli errori per tutte le richieste Ajax. Imposterò il gestore ajaxError e visualizzerò l'errore su un div chiamato errorcontainer nella parte superiore del contenuto 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);
                 });

81

Devi convertire il file responseTextin JSON. Utilizzando JQuery:

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

5
+1 perché al momento questa è l'unica risposta CORRETTA a questa domanda! È possibile chiamare "jsonValue.Message" per ottenere il messaggio di eccezione.
Captain Sensible,

2
In realtà non è la risposta corretta perché la domanda non fa domande su JSON e la richiesta di esempio richiede specificamente HTML come risposta.
SingleShot

+1 corretto. Nota, è comune inviare un oggetto con codifica JSON tramite jqXHR.responseText (stringa). È quindi possibile utilizzare l'oggetto jsonValue come è necessario. Utilizzare la console Firebug per rivedere la risposta utilizzando console.log (jsonValue).
jjwdesign,

Questo mi dà "Uncaught SyntaxError: Unexpected number"
Ben Racicot

1
L'oggetto JSON analizzato viene reso disponibile tramite la proprietà responseJSON dell'oggetto jqXHR. Quindi non è necessario analizzare la proprietà responseText. Puoi semplicemente fare: console.log (jqXHR.responseJSON.Message)
Eric D'Souza,

37

Se si effettua una chiamata a asp.net, questo restituirà il titolo del messaggio di errore:

Non ho scritto tutto il formatErrorMessage da solo, ma lo trovo molto utile.

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

Questo è quello che ho fatto e funziona finora in un'applicazione MVC 5.

Il tipo di restituzione del controller è 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"};
}

E sul lato client questo è l'aspetto della funzione 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

Se qualcuno è qui come nel 2016 per la risposta, utilizzare .fail()per la gestione degli errori in quanto .error()obsoleto a partire da jQuery 3.0

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

spero possa essere d'aiuto


2
jqXHR.error()è deprecato (effettivamente rimosso) in jQuery 3.0, ma i callback errore non sono deprecati, per quanto ne so. success$.ajax()
Neil Conway,

16

Una soluzione generale / riutilizzabile

Questa risposta viene fornita per riferimento futuro a tutti coloro che si imbattono in questo problema. La soluzione consiste di due cose:

  1. Eccezione personalizzata ModelStateException che viene generata quando la convalida non riesce sul server (lo stato del modello segnala errori di convalida quando utilizziamo le annotazioni dei dati e utilizziamo parametri di azione del controller tipizzati)
  2. Filtro di errore dell'azione del controller personalizzato HandleModelStateExceptionAttribute che rileva l'eccezione personalizzata e restituisce lo stato di errore HTTP con errore di stato del modello nel corpo

Ciò fornisce l'infrastruttura ottimale per le chiamate jQuery Ajax per sfruttare appieno il potenziale successe i errorgestori.

Codice lato client

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

Codice lato server

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

    // create new user because validation was successful
}

L'intero problema è dettagliato in questo post del blog in cui puoi trovare tutto il codice per eseguirlo nella tua applicazione.


14

Ho trovato questo bello perché ho potuto analizzare il messaggio che stavo inviando dal server e visualizzare un messaggio amichevole per l'utente senza stacktrace ...

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

11

 error:function (xhr, ajaxOptions, thrownError) {
        alert(xhr.status);
        alert(thrownError);
      }
nell'errore di codice richiesta Ajax per errore di cattura connettersi tra client e server se si desidera mostrare il messaggio di errore dell'applicazione inviare nell'ambito di successo

ad esempio

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

Ciò è probabilmente causato dal fatto che i nomi dei campi JSON non hanno virgolette.

Cambia la struttura JSON da:

{welcome:"Welcome"}

per:

{"welcome":"Welcome"}

1
Questo non dovrebbe importare a meno che la chiave non sia una parola riservata in JS. Non vedo che questo sia il problema qui.
John Gibb,

1
JSON.stringify ({welcome: "Welcome"}) -> {"welcome": "Welcome"}
Thulasiram,

5

Credo che il gestore della risposta Ajax utilizzi il codice di stato HTTP per verificare se si è verificato un errore.

Quindi, se si lancia un'eccezione Java sul codice lato server, ma la risposta HTTP non ha un codice di stato 500 jQuery (o in questo caso probabilmente l' oggetto XMLHttpRequest ) supporrà che tutto vada bene.

Sto dicendo questo perché ho avuto un problema simile in ASP.NET in cui stavo lanciando qualcosa come ArgumentException ("Non so cosa fare ...") ma il gestore degli errori non stava sparando.

Ho quindi impostato il valore Response.StatusCodesu 500 o 200, sia che avessi un errore o meno.


5

jQuery.parseJSON è utile per successo ed errore.

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

Nell'oggetto xhr è stato generato un oggetto JSON dell'eccezione. Basta usare

alert(xhr.responseJSON.Message);

L'oggetto JSON espone altre due proprietà: 'ExceptionType' e 'StackTrace'


5

Questa funzione genera sostanzialmente chiavi API casuali univoche e, nel caso in cui non lo fosse, viene visualizzata una finestra di dialogo pop-up con messaggio di errore

Nella pagina di visualizzazione:

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

Dal controller:

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

Il parametro callback facoltativo consente di specificare una funzione di callback da eseguire al completamento del metodo load (). La funzione di callback può avere diversi parametri:

Tipo: Funzione (jqXHR jqXHR, String textStatus, String errorThrown)

Una funzione da chiamare se la richiesta fallisce. La funzione riceve tre argomenti: l'oggetto jqXHR (in jQuery 1.4.x, XMLHttpRequest), una stringa che descrive il tipo di errore che si è verificato e un oggetto facoltativo di eccezione, se presente. I valori possibili per il secondo argomento (oltre a null) sono "timeout", "errore", "abort" e "parsererror". Quando si verifica un errore HTTP, errorThrown riceve la parte testuale dello stato HTTP, ad esempio "Non trovato" o "Errore interno del server". A partire da jQuery 1.5, l'impostazione dell'errore può accettare una matrice di funzioni. Ogni funzione verrà chiamata a turno. Nota: questo gestore non viene chiamato per richieste di script JSONP tra domini e tra domini.


4
$("#save").click(function(){
    $("#save").ajaxError(function(event,xhr,settings,error){
        $(this).html{'error: ' (xhr ?xhr.status : '')+ ' ' + (error ? error:'unknown') + 'page: '+settings.url);
    });
});

3

Lancia una nuova eccezione sul server utilizzando:

Response.StatusCode = 500

Response.StatusDescription = ex.Message ()

Credo che StatusDescription sia restituito alla chiamata Ajax ...

Esempio:

        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

Anche se sono passati molti anni da quando questa domanda è stata posta, non trovo ancora xhr.responseTextla risposta che cercavo. Mi ha restituito una stringa nel seguente formato:

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

che sicuramente non voglio mostrare agli utenti. Quello che stavo cercando è qualcosa di seguito:

alert(xhr.responseJSON.message);

xhr.responseJSON.message mi dà il messaggio esatto dall'oggetto Json che può essere mostrato agli utenti.


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

Se esiste un modulo, invia con validate

usa semplicemente il resto del codice

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

... ... });


0

Per prima cosa dobbiamo impostare <serviceDebug includeExceptionDetailInFaults = "True" /> in web.config:

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

Oltre a quello a livello jquery nella parte di errore, è necessario analizzare la risposta all'errore che contiene un'eccezione come:

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

Quindi utilizzando r.Message è possibile mostrare effettivamente il testo dell'eccezione.

Controlla il codice completo: http://www.codegateway.com/2012/04/jquery-ajax-handle-exception-thrown-by.html

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.