【问题标题】:Implementing ASP.NET MVC error handling using Castle Windsor's Dynamic Proxies使用 Castle Windsor 的动态代理实现 ASP.NET MVC 错误处理
【发布时间】:2015-11-05 09:37:12
【问题描述】:
我花了很长时间试图让 ASP.NET MVC [HandleError] attribute 在我的网站中工作。使用框架提供的解决方案似乎是个好主意,但我无法让它做任何有用的事情。然后我尝试编写自己的属性(主要是为了让我可以使用调试器进入代码),但是虽然我的代码似乎在做所有正确的事情,但在它执行之后,框架接管并做了一些神秘的事情。最后我尝试了 MVC Contrib 的 [Rescue] attribute,它更好,但我仍然无法让它做我想做的事情。
一个问题是嵌入在 aspx / ascx 页面中的代码中引发的异常被包裹在 HttpException 和 WebHttpException 中。
对我来说另一个问题是系统非常不透明。我基本上是在将输入插入到一个黑匣子中,并考虑到一些期望的输出,但不知道(除了文档,这似乎不是很准确/彻底)它们之间的关系是什么。
那么,该怎么办?
【问题讨论】:
标签:
asp.net-mvc
error-handling
castle-windsor
castle-dynamicproxy
【解决方案1】:
我选择了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;
}
}