Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在Asp.NETMVC针对Ajax请求的操作中,处理未处理异常(错误500响应)的最佳策略是什么?_C#_Asp.net Mvc_Json_Exception Handling - Fatal编程技术网

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

C# 在Asp.NETMVC针对Ajax请求的操作中,处理未处理异常(错误500响应)的最佳策略是什么?,c#,asp.net-mvc,json,exception-handling,C#,Asp.net Mvc,Json,Exception Handling,我对如何处理这种情况感到困惑 通常,当发生未处理的ASP.Net异常时,服务器会发回某种类型的HTML消息,可以是默认的ASP.Net错误处理程序,也可以是自定义的错误处理程序。不过,不管是哪种情况,HTML都会被发回(通常,让页面变得友好是个好主意) 但是,我遇到了一个问题,即Asp.net MVC控制器操作中出现了未处理的异常,这些操作预期会为Ajax调用返回JSON。当javascript读取返回的页面(是HTML而不是预期的JSON)时,由于无法将响应转换为JSON(现在我使用的是Ext

我对如何处理这种情况感到困惑

通常,当发生未处理的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请求,仍然保持常规错误页面用户友好?

您可以使用自定义ActionFilter,然后在其中,如果是javascript请求,则可以将响应格式化为JSON对象,而不是HTML页面。HandleError将是一个考虑扩展基类的好地方


如果您不想执行actio筛选器,另一种选择是覆盖控制器中的OneException,并将exceptionContext.Result设置为新的JsonResult,表示失败。

以下是我解决此问题的方法:

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

您可以在控制器中重写OneException,并加入一些逻辑以返回JSON错误响应,您需要在javascript调用代码中处理该响应:

protected override void OnException(ExceptionContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAjaxRequest())
        {
            filterContext.Result = Json("...");
        }
        else
        {
            base.OnException(filterContext);
        }
    }

如果您想“正确地”执行此操作,可以使用几乎相同的代码编写actionfilter,并将其应用于所有控制器。如果您使用的是MVC3,则可以将其设置为全局筛选器,以便将其应用于所有控制器。

您可能希望从HandleErrorAttribute继承,并重写OneException。这样,你的过滤器只有在出现异常时才会启动,而不是针对每个请求启动。由于代码原因,将此标记为答案@卖花人:哦,嗯,听起来不错。有机会的话我会试一试。谢谢客户端已经设置为确定是否发生了500错误,并解析它接收到的任何json。问题是,在此解决方案之前,服务器只返回HTML错误响应,我需要一个JSON错误响应。@adamjford幸运的是,我已经在使用Elmah,所以我知道它是什么。我很高兴您添加了这个,因为手动记录错误非常重要,因为如果您设置ExceptionHandling=true,将阻止Elmah进入。并且ExceptionHandling=true似乎是必需的,否则您将获得默认的HTML 500响应。在代码“正常”的情况下,try/catch也没有帮助,但异常仅在框架尝试执行ActionResult时发生-例如,如果您返回一个具有uint64值的对象,则会出现json序列化错误,即使代码中没有抛出异常。因此,您需要接受答案中的筛选器或OneException处理程序。