针对Ajax请求的Asp.Net MVC操作中处理未处理的异常(错误500响应)的最佳策略是什么?

时间:2011-01-19 14:53:19

标签: c# asp.net-mvc json exception-handling

我对如何处理这种情况很困惑。

通常,当发生未处理的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请求用户友好?

3 个答案:

答案 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。