aspnet mvc has the HandleError filter that will return a view if an error occurs, but if an error occurs when calling a JsonResult Action how can I return a JSON object that represents an error?
I don't want to wrap the code in each action method that returns a JsonResult in a try/catch to accomplish it, I'd rather do it by adding a 'HandleJsonError' attribute or using the existing HandleError attribute to the required action methods.
In short, the way to go can be to extend the HandleErrorAttribute, like this:
public class OncHandleErrorAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext context)
{
// Elmah-Log only handled exceptions
if (context.ExceptionHandled)
ErrorSignal.FromCurrentContext().Raise(context.Exception);
if (context.HttpContext.Request.IsAjaxRequest())
{
// if request was an Ajax request, respond with json with Error field
var jsonResult = new ErrorController { ControllerContext = context }.GetJsonError(context.Exception);
jsonResult.ExecuteResult(context);
context.ExceptionHandled = true;
}
else
{
// if not an ajax request, continue with logic implemented by MVC -> html error page
base.OnException(context);
}
}
}
Remove Elmah logging code line if you don't need it. I use one of my controllers to return a json based on an error and context. Here is the sample:
public class ErrorController : Controller
{
public ActionResult GetJsonError(Exception ex)
{
var ticketId = Guid.NewGuid(); // Lets issue a ticket to show the user and have in the log
Request.ServerVariables["TTicketID"] = ticketId.ToString(); // Elmah will show this in a nice table
ErrorSignal.FromCurrentContext().Raise(ex); //ELMAH Signaling
ex.Data.Add("TTicketID", ticketId.ToString()); // Trying to see where this one gets in Elmah
return Json(new { Error = String.Format("Support ticket: {0}\r\n Error: {1}", ticketId, ex.ToString()) }, JsonRequestBehavior.AllowGet);
}
I add some ticket info above, you can ignore this. Due to the way the filter is implemented (extends the default HandleErrorAttributes) we can remove then HandleErrorAttribute from the global filters:
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new GlobalAuthorise());
filters.Add(new OncHandleErrorAttribute());
//filters.Add(new HandleErrorAttribute());
}
This is basically it. You can read my blog entry for more detailed info, but for the idea, above should suffice.
Take a look at the MVC implementation of HandleErrorAttribute. It returns a ViewResult. You could write your own version (HandleJsonErrorAttribute) that returns a JsonResult.
Maybe you could create your own Attribute and have a constructor value that takes an enum value of View or Json. Below is what Im using for a custom Authorization Attribute to demonstrate what I mean. This way when authentication fails on a json request it responds with a json error and the same with if it returns a View.
public enum ActionResultTypes
{
View,
Json
}
public sealed class AuthorizationRequiredAttribute : ActionFilterAttribute, IAuthorizationFilter
{
public ActionResultTypes ActionResultType { get; set; }
public AuthorizationRequiredAttribute(ActionResultTypes actionResultType)
{
this.ActionResultType = ActionResultType;
}
}
//And used like
[AuthorizationRequired(ActionResultTypes.View)]
public ActionResult About()
{
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With