7

Si un error de carga de página normal puedo informar los detalles de la excepción al usuario a través de la vista Error y el modelo HandleErrorInfo.Informes de errores de Ajax invocaron métodos PartialView en MVC

Si una llamada esperando un ajaxJson errores de resultado, que puede manejar de manera explícita el error y pasar datos al cliente:

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

Por lo tanto, mi problema, no puedo ver ninguna manera de informar sobre los detalles del error desde una llamada Ajax a una acción que devuelve una vista parcial.

$.ajax({ 
    url: 'whatever/trevor', 
    error: function (jqXHR, status, error) { 
     alert('An error occured: ' + error); 
    }, 
    success: function (html) { 
     $container.html(html); 
    } 
}); 

Esto sólo informar de un código de error HTTP (por ejemplo, error interno del servidor) que no es útil para el cliente. ¿Hay algún truco inteligente para pasar un resultado exitoso de PartialView (html) o?

Evaluando explícitamente el html desde el ViewResult y devolviéndolo como parte de un objeto Json junto con un estado que parece demasiado apestoso. ¿Existe un patrón establecido para manejar este escenario?

Respuesta

14

controlador de acción:

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

A continuación, se define un controlador de errores global para nuestra aplicación:

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

Así es como el ErrorsController utilizado en el controlador de errores global podría ser similar. Probablemente podríamos definir algunos puntos de vista personalizados para las acciones 404 y 500:

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

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

entonces podríamos suscribir un global error handler para todos los errores de AJAX de manera que no tenemos que repetir este código de manejo de errores para todas las peticiones AJAX, pero si queríamos podíamos repetirlo:

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

Y finalmente disparar una petición AJAX a la acción del controlador que esperamos devolver un HTML parcial en este caso:

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

Darin su conocimiento de MVC me sorprende de nuevo. No entendí completamente un par de puntos aquí, pero descubrí que podía lograr algo similar un poco más simple con un filtro ajax registrado en filtros globales. Parece estar funcionando bien. Gracias. – fearofawhackplanet

+0

Solo una nota, si estás usando el código anterior para atrapar 404's y mostrar una página personalizada, probablemente quieras agregar un Response.TrySkipIisCustomErrors = true (.net 3.5 en adelante solo creo) –

+0

Funciona como un encanto, aweseome – Dilip

Cuestiones relacionadas