我对如何处理这种情况很困惑。
通常,当发生未处理的ASP.Net异常时,服务器会发回某种HTML消息,默认的Asp.Net错误处理程序或自定义错误处理程序。在任何一种情况下,都会发回HTML(通常最好让页面用户友好)。
但是,我遇到了一个问题,即在Asp.net MVC控制器操作中发生未处理的异常,这些操作有望为Ajax调用返回JSON。当javascript读取返回的页面(它是HTML而不是预期的JSON)时,由于无法将响应转换为JSON(现在我正在使用ExtJS)而崩溃。我希望在异常时返回Json,以便通知用户发生了错误。
我能想到的唯一解决方案是在每个返回Json的操作中执行以下操作:
try { .... }
catch (Exception ex)
{
return Json(new { success = false, msg = ex.Message });
}
我不喜欢那种方法,因为它要求我捕获所有异常(由于显而易见的原因这是不好的)并且它要求我用同样的异常处理代码来加密每个JsonResult
动作(这使得很难稍后改变)。
是否有更好的方法只返回返回Json的操作方法更合适的错误结果,但仍然保持常规错误页面对非Ajax Web请求用户友好?
答案 0 :(得分:12)
以下是我解决这个问题的方法:
public class HandleJsonError : HandleErrorAttribute
{
public override void OnException(ExceptionContext exceptionContext)
{
if (!exceptionContext.HttpContext.Request.IsAjaxRequest() || exceptionContext.Exception == null) return;
exceptionContext.HttpContext.Response.StatusCode = (int) HttpStatusCode.InternalServerError;
exceptionContext.Result = new JsonResult
{
Data = new
{
exceptionContext.Exception.Message,
exceptionContext.Exception.StackTrace
}
};
exceptionContext.ExceptionHandled = true;
}
}
答案 1 :(得分:4)
您可以在控制器中覆盖OnException并输入一些逻辑来返回您需要在javascript调用代码中处理的JSON错误响应:
protected override void OnException(ExceptionContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.Result = Json("...");
}
else
{
base.OnException(filterContext);
}
}
如果你想'正确',你可以用几乎相同的代码编写一个actionfilter并将其应用到所有控制器。如果您使用的是MVC3,则可以将其设置为全局过滤器,以便它适用于所有控制器。
答案 2 :(得分:1)
您可以使用自定义ActionFilter,然后在其中如果是javascript请求,则可以将响应格式化为JSON对象而不是HTML页面。 HandleError是一个从扩展基类的好地方。
如果你不想做一个actio过滤器,另一个选择是覆盖你的控制器中的OnException,并将exceptionContext.Result设置为一个指示失败的新JsonResult。