我正在开发一个 ASP.NET 的MVC 3应用程序。在我们应用程序的所谓"业务层"中,我们决定始终根据情况抛出一些特定类型的异常。当用户尝试执行他未授权的操作时,我们有一个异常类型层次结构,当应用程序找不到给定项目(通过 Id 或名称或其他任何)时,我们有一个特殊异常。
这在我们的 C# 代码中如下所示:
// ... more stuff
public Something GetSomething(int id, User currentUser){
var theSomething = SomethingRepository.Get(id);
if(theSomething == null){
throw new SomethingNotFoundException(id, "more details");
}
if(!PermissionService.CanLoadSomething(currentUser)){
throw new NotAuthorizedException("You shall not pass");
}
// the rest of the method etc etc
// ...
}
。其中SomethingNotFoundException
和NotAuthorizedException
是自定义Exception
s 。
这种异常和 Http 状态代码(404 未找到/403 禁止)之间存在某种直接映射,我们希望我们的控制器方法相应地处理这些错误(显示 404/403 CustomError 页面和类似的东西)。现在,我们想要的是避免在我们的控制器操作中执行此操作:
public ViewResult Get(int id){
try{
var theSomething = MyService.GetSomething(id, theUser);
}
catch(SomethingNotFoundException ex){
throw new HttpException(404, ex);
}
catch(NotAuthorizedExceptionex){
throw new HttpException(403, ex);
}
}
我很确定一定有一种方法可以使用自定义 HandleErrorAttribute 或自定义 ActionFilterAttribute 并将其注册到 Global.asax,但我无法弄清楚如何让它工作。
尝试 1:句柄错误属性
我首先尝试创建HandleErrorAttribute的子类,覆盖OnException
方法如下:
public override void OnException(ExceptionContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
Exception exception = filterContext.Exception;
// Map some of the Business Exception to correspounding HttpExceptions !
if (exception is ObjectNotFoundException)
{
// consider it as a NotFoundException !
exception = new HttpException((int)HttpStatusCode.NotFound, "Not found", exception);
filterContext.Exception = exception;
}
else if (exception is NotAuthorizedException)
{
// consider it as a ForbiddenException
exception = new HttpException((int)HttpStatusCode.Forbidden, "Forbidden", exception);
filterContext.Exception = exception;
}
base.OnException(filterContext);
}
。并将其添加到 Global.asax 中的GlobalFilterCollection
中......但它仍然像通常的 500 错误一样处理,而不是显示 404/403 自定义错误页面......
尝试 2:操作过滤器属性
我还尝试将其设为ActionFilterAttribute
并覆盖OnActionExecuted
方法,如下所示:
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
Exception exception = filterContext.Exception;
if(exception!=null)
{
// Map some of the Business Exception to correspounding HttpExceptions !
if (exception is ObjectNotFoundException)
{
// consider it as a NotFoundException !
var wrappingException = new HttpException((int)HttpStatusCode.NotFound, "Not found", exception);
exception = wrappingException;
filterContext.Exception = exception;
}
else if (exception is NotAuthorizedException)
{
// consider it as a ForbiddenException
var wrappingException = new HttpException((int)HttpStatusCode.Forbidden, "Forbidden", exception);
exception = wrappingException;
filterContext.Exception = exception;
}
}
base.OnActionExecuted(filterContext);
}
。但是,我仍然得到 500 错误页面而不是 404 或 403 ......
我做错了什么吗?有没有更好的方法?
嗯,有几个选择。
你可能想要:这家伙的解决方案
你可以像这个人一样做。
您可以有一个所有类都继承自的基控制器类,并使用以下方法。 这就是我上一家公司解决这个问题的方式。
protected override void OnException(ExceptionContext filterContext)
{
Console.WriteLine(filterContext.Exception.ToString());
}