使用Castle Windsor的Dynamic Proxies实现ASP.NET MVC错误处理

时间:2015-08-12 16:40:15

标签: asp.net-mvc error-handling castle-windsor castle-dynamicproxy

我花了很长时间试图让ASP.NET MVC [HandleError] attribute在我的网站上运行。使用框架提供的解决方案似乎是一个好主意,但我无法让它做任何有用的事情。然后我尝试编写自己的属性(主要是为了让我可以使用调试器进入代码),但是虽然我的代码似乎做了所有正确的事情,但在执行框架后接管并做了一些神秘的事情。最后我尝试了MVC Contrib的[Rescue] attribute,这更好,但我仍然无法做到我想做的事。

一个问题是嵌入在aspx / ascx页面中的代码中抛出的异常会被包装在HttpException和WebHttpException中。

对我来说另一个问题是系统非常不透明。我基本上把输入插入到一个黑盒子中,并考虑了一些想要的输出,但是不知道(除了文档,这看起来不是非常准确/彻底)它们之间的关系是什么。

那么,该怎么办?

1 个答案:

答案 0 :(得分:0)

我使用下面的代码前往Dynamic Proxies in Castle Windsor,它尝试处理数据库错误,我有一个特定的异常(AccessDBException)。

_alreadyAttemptedToShowErrorPage是在错误页面抛出异常的情况下停止无限递归。

GetAccessDBException(...)方法在异常堆栈中的任何位置查找相关异常,以防aspx / ascx代码出现问题。

代码要求所有控制器都派生一个BaseController类。该类用于添加CreateErrorView(...)方法(作为标准View(...)方法受保护)

public class AccessDBExceptionHandlingDynamicProxy : IInterceptor
{
    private bool _alreadyAttemptedToShowErrorPage;

    public AccessDBExceptionHandlingDynamicProxy()
    {
        _alreadyAttemptedToShowErrorPage = false;
    }

    public void Intercept(IInvocation invocation)
    {
        Contract.Requires(invocation.Proxy is BaseController);

        try
        {
            invocation.Proceed();
        }
        catch (HttpException e)
        {
            if (_alreadyAttemptedToShowErrorPage == true) throw e;
            _alreadyAttemptedToShowErrorPage = true;

            var dbException = GetAccessDBException(e);

            if (dbException != null)
            {
                var baseController = (invocation.Proxy as BaseController);
                var view = baseController.CreateErrorView("AccessDBException", new AccessDBExceptionViewModel(dbException));

                baseController.Response.Clear();
                baseController.Response.StatusCode = (int) HttpStatusCode.InternalServerError; 
                view.ExecuteResult(baseController.ControllerContext);
                baseController.Response.End();
            }
            else
            {
                throw e;
            }
        }
    }

    private static AccessDBException GetAccessDBException(HttpException e)
    {
        AccessDBException dbException = null;
        Exception current = e;

        while (dbException == null && current != null)
        {
            if (current is AccessDBException) dbException = (current as AccessDBException);
            current = current.InnerException;
        }

        return dbException;
    }
}