Controller中的异常处理(ASP.NET MVC)

Ser*_*uss 21 c# error-handling asp.net-mvc

当您从控制器中的操作调用的自己的代码抛出异常时应该如何处理?我看到很多最佳实践的例子,其中根本没有try-catch语句.例如,从存储库访问数据:

public ViewResult Index()
{
    IList<CustomModel> customModels = _customModelRepository.GetAll();
    return View(customModels);
}
Run Code Online (Sandbox Code Playgroud)

显然,如果调用它是一个无法访问的数据库,并且我们正在使用像Entity Framework这样的ORM,则此代码可能会抛出异常.

但是,我能看到的所有事情都会发生异常,并且会向用户显示一条令人讨厌的错误消息.

我知道HandleError属性,但据我所知,如果发生未处理的异常,它主要用于将您重定向到错误页面.

当然,这段代码可以包装在try-catch中,但不能很好地分离,特别是如果你有更多的逻辑:

public ViewResult Index()
{
    if (ValidationCheck())
    {
        IList<CustomModel> customModels = new List<CustomModel>();
        try
        {
            customModels = _customModelRepository.GetAll();
        }
        catch (SqlException ex)
        {
            // Handle exception
        }

        if (CustomModelsAreValid(customModels))
            // Do something
        else
            // Do something else
    }

    return View();
}
Run Code Online (Sandbox Code Playgroud)

以前我已经提取出所有可能会将数据库调用之类的异常引入DataProvider类的代码,该类处理错误并返回消息以向用户显示消息.

我想知道处理这个问题的最佳方法是什么?我并不总是希望返回错误页面,因为一些例外不应该这样做.相反,应该以正常视图显示给用户的错误消息.我以前的方法是正确的还是有更好的解决方案?

Nov*_*Joe 23

我做了三件事来显示更多用户友好的消息:

  1. 利用全局异常处理程序.对于MVC:Global.asax中的Application_Error.在这里学习如何使用它:http://msdn.microsoft.com/en-us/library/24395wz3(v = vs.100).aspx
  2. 我将Exception子类化为UserFriendlyException.我尽我所能在我的所有底层服务类中抛出这个UserFriendlyException而不是一个普通的旧Exception.我总是尝试将用户有意义的消息放在这些自定义异常中.其主要目的是能够对Application_Error方法中的异常进行类型检查.对于UserFriendlyExceptions,我只使用我在服务中深入设置的用户友好消息,例如"嘿!91度不是有效的纬度值!".如果它是一个常规异常,那么有些情况我没有处理,所以我显示了一个更通用的错误消息,如"哎呀,出错了!我们会尽力解决这个问题!".
  3. 我还创建了一个ErrorController,负责呈现用户友好的视图或JSON.这是控制器,其方法将从Application_Error方法调用.

编辑: 我想我会提到ASP.NET Web API,因为它密切相关.因为Web API端点的使用者不一定是浏览器,所以我喜欢稍微处理错误.我仍然使用"FriendlyException"(上面的#2),但不是重定向到ErrorController,而是让我的所有端点返回某种包含Error属性的基类型.因此,如果异常一直到Web API控制器,我确保将该错误粘贴在API响应的Error属性中.此错误消息将是从API控制器依赖的类中冒出的友好消息,或者如果异常类型不是FriendlyException,则它将是通用消息.那样,消费客户端可以简单地检查API响应的Error属性是否为空.如果错误存在则显示消息,否则照常进行.好消息是,由于友好的消息概念,消息对于用户而言可能比通用的"错误!"更有意义.信息.我在使用Xamarin编写移动应用程序时使用此策略,我可以在我的Web服务和iOS/Android应用程序之间共享我的C#类型.


Pat*_*ins 18

使用Asp.Net MVC,您还可以为您的控制器覆盖OnException方法.

protected override void OnException(ExceptionContext filterContext)
{
    if (filterContext.ExceptionHandled)
    {
        return;
    }
    filterContext.Result = new ViewResult
    {
        ViewName = ...
    };
    filterContext.ExceptionHandled = true;
}
Run Code Online (Sandbox Code Playgroud)

这允许您重定向到自定义错误页面,如果您愿意,可以使用引用该异常的消息.

  • 我同意这是一个很好的答案.在自定义基本控制器中覆盖OnException,并使所有其他控制器继承它.将此与用户友好异常的概念相结合,您将获得一个很好的解决方案. (3认同)