我有一个使用MVC3的网站。我有一个n层架构,我很好奇在什么级别最好捕获错误。
对于isntance,假设我有一个Students表,我有一个StudentRepository,其函数如下: StudentRepository.GetHightestGrade(studentId)
所以我应该让我的Repositry函数有一个try / catch块 - 或者我应该将try / catch直接放入ActionResult函数中。或者我会更好地添加到业务类中,然后我的ActionResult函数会执行诸如
之类的操作Business.GetHighestGrade(studentId)和该函数只是有一个try / catch并调用Repository函数?
答案 0 :(得分:1)
这取决于你想要捕获的内容,你是否只想默默地失败?你想记录错误吗?你想返回一个视图来通知用户出了什么问题吗?
如果您只想通知用户,请在控制器中捕获它。 如果你想记录它,然后在你的仓库中捕获它,并让你的repo通过一些日志服务进行日志记录,你可以使用一些更高级的服务来执行调用捕获错误并记录它,但这可能是一个过度杀死。
答案 1 :(得分:1)
如果你试图阻止错误冒泡堆栈,你应该只在try / catch中包装方法。通常,最好将try / catch放在顶层,以保护用户免受错误的影响。在特殊情况下,较低层通常应抛出异常,您应该只尝试在较高层捕获它们。
你会发现你的代码在没有大量try / catch块的情况下更具可读性,我个人尽量避免使用它们,并让MVC3 HandleError过滤器属性负责显示错误消息。但是,有时您可能希望在它抛出异常时重试一个操作,这会成为一个很好的try / catch候选者。
看一下ELMAH - 使用它可以帮助你编写代码,避免出现异常。但是,如果您期望异常,则应该只显式尝试/ catch,并且希望采取一些操作来响应它。
答案 2 :(得分:0)
您应该为自定义异常编写全局过滤器属性。捕获该过滤器上的所有异常并返回视图。像这样的东西
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Text;
namespace Filters
{
public sealed class HandleException : FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
if (filterContext == null)
throw new ArgumentException("filterContext");
else if (typeof(AjaxException).IsInstanceOfType(filterContext.Exception) && !filterContext.ExceptionHandled)
{
filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.ContentEncoding = Encoding.UTF8;
filterContext.HttpContext.Response.HeaderEncoding = Encoding.UTF8;
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
filterContext.HttpContext.Response.StatusCode = 400;
filterContext.Result = new ContentResult
{
Content = "Unexpected error",
ContentEncoding = Encoding.UTF8,
};
}
}
}
}
并将此过滤器添加到global.asax
中的全局过滤器属性答案 3 :(得分:0)
存储库级别必须具有处理sql异常并将错误写入Log的try-catch构造。如果您的业务逻辑很复杂并且可能产生错误或不一致的状态 - 您应该检查它并将错误写入Log。如果您想通知用户有关错误的事情(如果业务逻辑提供例外) - 您应该在控制器操作中使用try-catch构造并使用ModelState.AddModelError()
作为通知用户的方法之一,或使用其他方式将有关错误的信息传递给视图。最后,必须在Application_Start中的global.asax中注册class CustomErrorFilter : IExceptionFilter
:
GlobalFilters.Filters.Add(new LoggingFilter());
该过滤器应写入记录控制器级别上发生的所有未处理错误。
请记住,您的代码提供了正常的工作流程,并且可以提供错误工作流程(将异常作为组织错误工作流程的方法之一,或返回一些错误代码)。你应该指望它并处理两个工作流程。