7

Se un normale errore di caricamento della pagina è possibile segnalare i dettagli delle eccezioni all'utente tramite la vista Error e il modello .Gli errori di segnalazione da Ajax hanno richiamato i metodi PartialView in MVC

Se un ajax chiamata in attesa di un Json errori di risultato, io in grado di gestire in modo esplicito l'errore e passare informazioni al cliente:

public JsonResult Whatever() 
{ 
    try 
    { 
     DoSomething(); 
     return Json(new { status = "OK" }); 
    } 
    catch (Exception e) 
    { 
     return Json(new { status = "Error", message = e.Message }); 
    } 
} 

Quindi, il mio problema, non riesco a vedere alcun modo di riferire dettagli dell'errore da una chiamata Ajax a un'azione che restituisce una vista parziale.

Questo segnalerà solo un codice di errore Http (ad esempio Internal Server Error) che non è utile per il client. C'è qualche trucco intelligente per passare un risultato di PartialView (html) con successo o un messaggio di errore?

Valutare esplicitamente il codice HTML dallo ViewResult e restituirlo come parte di un oggetto Json insieme a uno stato sembra troppo maleodorante. C'è un modello stabilito per gestire questo scenario?

risposta

14

azione di controllo:

public ActionResult Foo() 
{ 
    // Obviously DoSomething could throw but if we start 
    // trying and catching on every single thing that could throw 
    // our controller actions will resemble some horrible plumbing code more 
    // than what they normally should resemble: a.k.a being slim and focus on 
    // what really matters which is fetch a model and pass to the view 

    // Here you could return any type of view you like: JSON, HTML, XML, CSV, PDF, ... 

    var model = DoSomething(); 
    return PartialView(model); 
} 

Poi definiamo un gestore di errore globale per la nostra applicazione:

protected void Application_Error(object sender, EventArgs e) 
{ 
    var exception = Server.GetLastError(); 
    var httpException = exception as HttpException; 
    Response.Clear(); 
    Server.ClearError(); 

    if (new HttpRequestWrapper(Request).IsAjaxRequest()) 
    { 
     // Some error occurred during the execution of the request and 
     // the client made an AJAX request so let's return the error 
     // message as a JSON object but we could really return any JSON structure 
     // we would like here 

     Response.StatusCode = 500; 
     Response.ContentType = "application/json"; 
     Response.Write(new JavaScriptSerializer().Serialize(new 
     { 
      errorMessage = exception.Message 
     })); 
     return; 
    } 

    // Here we do standard error handling as shown in this answer: 
    // http://stackoverflow.com/q/5229581/29407 

    var routeData = new RouteData(); 
    routeData.Values["controller"] = "Errors"; 
    routeData.Values["action"] = "General"; 
    routeData.Values["exception"] = exception; 
    Response.StatusCode = 500; 
    if (httpException != null) 
    { 
     Response.StatusCode = httpException.GetHttpCode(); 
     switch (Response.StatusCode) 
     { 
      case 404: 
       routeData.Values["action"] = "Http404"; 
       break; 
      case 500: 
       routeData.Values["action"] = "Http500"; 
       break; 
     } 
    } 

    IController errorsController = new ErrorsController(); 
    var rc = new RequestContext(new HttpContextWrapper(Context), routeData); 
    errorsController.Execute(rc); 
} 

Ecco come l'ErrorsController utilizzato nel gestore di errore globale potrebbe sembrare. Probabilmente potremmo definire alcune visualizzazioni personalizzate per le azioni 404 e 500:

public class ErrorsController : Controller 
{ 
    public ActionResult Http404() 
    { 
     return Content("Oops 404"); 
    } 

    public ActionResult Http500() 
    { 
     return Content("500, something very bad happened"); 
    } 
} 

allora potremmo sottoscrivere una global error handler per tutti gli errori AJAX in modo da non dover ripetere questo codice di gestione degli errori per tutte le richieste AJAX, ma se volessimo potremmo ripeterlo:

$('body').ajaxError(function (evt, jqXHR) { 
    var error = $.parseJSON(jqXHR.responseText); 
    alert('An error occured: ' + error.errorMessage); 
}); 

E finalmente sparare una richiesta AJAX per l'azione di controllo che ci auguriamo possa restituire un parziale HTML in questo caso:

$.ajax({ 
    url: 'whatever/trevor', 
    success: function (html) { 
     $container.html(html); 
    } 
}); 
+1

Darin la vostra conoscenza di MVC mi sbalordisce ancora una volta. Non ho compreso completamente un paio di punti qui, ma ho capito che avrei potuto ottenere qualcosa di simile un po 'più semplicemente con un filtro ajax registrato nei filtri globali. Sembra funzionare bene. Grazie. – fearofawhackplanet

+0

Solo una nota, se stai usando il codice sopra per intrappolare 404 e mostrare una pagina personalizzata probabilmente vuoi aggiungere un Response.TrySkipIisCustomErrors = true (.net 3.5 in poi credo soltanto) –

+0

Funziona come un incantesimo, fantastico – Dilip

Problemi correlati