2

我正在开发一个 ASP.NET MVC 3 应用程序。在我们App所谓的“业务层”中,我们做出了一个决定,总是根据情况抛出一些特定类型的异常。当用户试图做他未授权的事情时,我们有一个异常类型层次结构,以及当应用程序找不到给定项目(通过 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
    // ...
}

... custom s 的位置SomethingNotFoundException和位置。NotAuthorizedExceptionException

这种异常和 Http 状态码(404 Not Found / 403 Forbidden)之间存在某种直接映射,我们希望我们的 Controller 方法相应地处理这些错误(显示 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

我首先尝试创建一个 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);

}

...并将其添加到GlobalFilterCollectionGlobal.asax ...但它仍然像通常的 500 错误一样处理,而不是显示 404/403 自定义错误页面...

尝试 2:ActionFilterAttribute

我也尝试过使它成为一个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 ...

难道我做错了什么 ?有没有更好的方法?

4

1 回答 1

0

那么有几个选择。

你可能想要:这家伙的解决方案

你可以这样做这个家伙

您可以拥有一个所有类都继承自的基本 Controller 类,并使用以下方法。这就是我上一家公司解决这个问题的方式。

protected override void OnException(ExceptionContext filterContext)
{
       Console.WriteLine(filterContext.Exception.ToString());
}
于 2013-02-20T01:29:47.760 回答