Reporting errors from Ajax caused PartialView methods in MVC

If common page loading errors occur, I can report the details of the exception to the user through the Error and HandleErrorInfo .

If the ajax call is expecting a Json result Json , I can explicitly handle the error and pass the details to the client:

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

So, my problem, I see no way to report error data from an Ajax call to an action that returns a partial view.

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

Only the Http error code (for example, Internal Server Error) is reported, which is not useful to the client. Is there any clever trick to convey either a successful PartialView (html) result or an error message?

Explicitly evaluating the html from ViewResult and returning it as part of the Json object along with the status seems too smelly. Is there an installed template to handle this script?

+7
source share
2 answers

Controller action:

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

Then we define a global error handler for our application:

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

This is what the ErrorsController used in the global error handler would look like. We could probably define some custom views for 404 and 500 actions:

 public class ErrorsController : Controller { public ActionResult Http404() { return Content("Oops 404"); } public ActionResult Http500() { return Content("500, something very bad happened"); } } 

Then we could subscribe to the global error handler for all AJAX errors so that we would not have to repeat this error handling code for all AJAX, but if we wanted, we could repeat it:

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

And finally, we run an AJAX request for a controller action, which we hope will return partial HTML in this case:

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

Create an overridden version of HandleErrorAttribute (JsonHandleErrorAttribute?) And add [JsonHandleError] to the json action.

Have a look at the AjaxAuthorizeAttribute in asp.net mvc [handleerror] [authorize] using JsonResult?

0
source

All Articles