asp.net-mvc jquery asp.net-mvc-3

ASP.NET MVC Ajax Tratamiento de errores



asp.net-mvc jquery (6)

¿Cómo manejo las excepciones lanzadas en un controlador cuando jquery ajax llama a una acción?

Por ejemplo, me gustaría un código javascript global que se ejecute en cualquier tipo de excepción de servidor durante una llamada ajax que muestra el mensaje de excepción si está en modo de depuración o simplemente un mensaje de error normal.

En el lado del cliente, llamaré a una función sobre el error ajax.

En el lado del servidor, ¿necesito escribir un filtro de acción personalizado?


De acuerdo con la respuesta de aleho, aquí hay un ejemplo completo. Funciona como un encanto y es súper simple.

Código de controlador

[HttpGet] public async Task<ActionResult> ChildItems() { var client = TranslationDataHttpClient.GetClient(); HttpResponseMessage response = await client.GetAsync("childItems); if (response.IsSuccessStatusCode) { string content = response.Content.ReadAsStringAsync().Result; List<WorkflowItem> parameters = JsonConvert.DeserializeObject<List<WorkflowItem>>(content); return Json(content, JsonRequestBehavior.AllowGet); } else { return new HttpStatusCodeResult(response.StatusCode, response.ReasonPhrase); } } }

Código Javascript en la vista

var url = ''@Html.Raw(@Url.Action("ChildItems", "WorkflowItemModal")''; $.ajax({ type: "GET", dataType: "json", url: url, contentType: "application/json; charset=utf-8", success: function (data) { // Do something with the returned data }, error: function (xhr, status, error) { // Handle the error. } });

¡Espero que esto ayude a alguien más!


Desafortunadamente, ninguna de las respuestas es buena para mí. Sorprendentemente, la solución es mucho más simple. Regreso del controlador:

return new HttpStatusCodeResult(HttpStatusCode.BadRequest, e.Response.ReasonPhrase);

Y maneje como un error HTTP estándar en el cliente como desee.


Después de buscar en Google, escribo un simple envío de excepciones basado en el filtro de acción MVC:

public class HandleExceptionAttribute : HandleErrorAttribute { public override void OnException(ExceptionContext filterContext) { if (filterContext.HttpContext.Request.IsAjaxRequest() && filterContext.Exception != null) { filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError; filterContext.Result = new JsonResult { JsonRequestBehavior = JsonRequestBehavior.AllowGet, Data = new { filterContext.Exception.Message, filterContext.Exception.StackTrace } }; filterContext.ExceptionHandled = true; } else { base.OnException(filterContext); } } }

y escribe en global.ascx:

public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleExceptionAttribute()); }

y luego escriba esta secuencia de comandos en el diseño o en la página Maestra:

<script type="text/javascript"> $(document).ajaxError(function (e, jqxhr, settings, exception) { e.stopPropagation(); if (jqxhr != null) alert(jqxhr.responseText); }); </script>

Finalmente debe activar el error personalizado. y luego disfrutarlo :)


Hice una solución rápida porque tenía poco tiempo y funcionó bien. Aunque creo que la mejor opción es usar un Filtro de excepciones, tal vez mi solución pueda ayudar en el caso de que se necesite una solución simple.

Hice lo siguiente. En el método del controlador, devolví un JsonResult con una propiedad "Correcto" dentro de los datos:

[HttpPut] public JsonResult UpdateEmployeeConfig(EmployeConfig employeToSave) { if (!ModelState.IsValid) { return new JsonResult { Data = new { ErrorMessage = "Model is not valid", Success = false }, ContentEncoding = System.Text.Encoding.UTF8, JsonRequestBehavior = JsonRequestBehavior.DenyGet }; } try { MyDbContext db = new MyDbContext(); db.Entry(employeToSave).State = EntityState.Modified; db.SaveChanges(); DTO.EmployeConfig user = (DTO.EmployeConfig)Session["EmployeLoggin"]; if (employeToSave.Id == user.Id) { user.Company = employeToSave.Company; user.Language = employeToSave.Language; user.Money = employeToSave.Money; user.CostCenter = employeToSave.CostCenter; Session["EmployeLoggin"] = user; } } catch (Exception ex) { return new JsonResult { Data = new { ErrorMessage = ex.Message, Success = false }, ContentEncoding = System.Text.Encoding.UTF8, JsonRequestBehavior = JsonRequestBehavior.DenyGet }; } return new JsonResult() { Data = new { Success = true }, }; }

Más tarde en la llamada ajax, solo pedí esta propiedad para saber si tenía una excepción:

$.ajax({ url: ''UpdateEmployeeConfig'', type: ''PUT'', data: JSON.stringify(EmployeConfig), contentType: "application/json;charset=utf-8", success: function (data) { if (data.Success) { //This is for the example. Please do something prettier for the user, :) alert(''All was really ok''); } else { alert(''Oups.. we had errors: '' + data.ErrorMessage); } }, error: function (request, status, error) { alert(''oh, errors here. The call to the server is not working.'') } });

Espero que esto ayude. ¡Feliz código! :PAG


Para manejar los errores de las llamadas ajax en el lado del cliente, asigna una función a la opción de error de la llamada ajax.

Para establecer un valor predeterminado de forma global, puede usar la función que se describe aquí: http://api.jquery.com/jQuery.ajaxSetup .


Si el servidor envía algún código de estado diferente a 200, se ejecuta la devolución de llamada de error:

$.ajax({ url: ''/foo'', success: function(result) { alert(''yeap''); }, error: function(XMLHttpRequest, textStatus, errorThrown) { alert(''oops, something bad happened''); } });

y para registrar un controlador de error global, puede usar el $.ajaxSetup() :

$.ajaxSetup({ error: function(XMLHttpRequest, textStatus, errorThrown) { alert(''oops, something bad happened''); } });

Otra forma es usar JSON. Para que pueda escribir un filtro de acción personalizado en el servidor que capta la excepción y los transforma en respuesta JSON:

public class MyErrorHandlerAttribute : FilterAttribute, IExceptionFilter { public void OnException(ExceptionContext filterContext) { filterContext.ExceptionHandled = true; filterContext.Result = new JsonResult { Data = new { success = false, error = filterContext.Exception.ToString() }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } }

y luego decora tu acción de controlador con este atributo:

[MyErrorHandler] public ActionResult Foo(string id) { if (string.IsNullOrEmpty(id)) { throw new Exception("oh no"); } return Json(new { success = true }); }

y finalmente invocarlo:

$.getJSON(''/home/foo'', { id: null }, function (result) { if (!result.success) { alert(result.error); } else { // handle the success } });