【发布时间】:2011-12-08 11:21:02
【问题描述】:
在我正在开发的应用程序中,我创建了一个轻量级记录器,它有两个用途。使用枚举“域”记录的错误将被记录到数据库中,而使用枚举“应用程序”记录的错误可以从服务中提取以显示给用户。
我正在使用 ninject InRequestScope 来允许在请求范围内维护错误集合。
我不确定的一个问题是我应该何时调用该函数将错误记录到数据库中。此函数使用事务将所有错误推送到数据库中。我的一个想法是让错误记录器使用 IDisposable,然后从 Dispose 方法调用 LogErrorsToDatabase() 方法。
这样做有什么问题吗?
ninject 会自动调用 dispose,还是我需要对其进行配置才能这样做?
我首先尝试将服务注入 Global.asax,但这出现了无法预料的问题。
编辑:我找到了一种更优雅的方法,所以为了将来参考,我将在下面详细说明。
我首先创建了一个自定义操作过滤器并使用属性注入来注入 IErrorLog 服务:
public class LogErrorsAttribute : ActionFilterAttribute
{
[Inject]
public IErrorQueue ErrorQueue { private get; set; }
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
ErrorQueue.CommitDatabaseLog();
base.OnResultExecuted(filterContext);
}
}
接下来我使用 Ninject 的 BindFilter 方法将此函数绑定到每个调用的操作:
BindFilter<LogErrorsAttribute>(FilterScope.Last, 0);
现在一切都完美而干净。
最终编辑:我注意到最近有人对此表示赞同,因此他们可能使用了我找到的解决方案。我确实在上次编辑中发现了解决方案的错误。似乎我的导航控制器正在触发此功能,在导航触发时,没有发生错误,这会写入 filtercontext 并在稍后被链下的操作调用时停止它的运行。为了解决这个问题,我使用了以下绑定代码:
kernel.BindFilter<LogErrorsAttribute>(FilterScope.Last, 0).When(
(context, ad) => !string.IsNullOrEmpty(ad.ActionName) && ad.ControllerDescriptor.ControllerName.ToLower() != "navigation");
这会阻止任何导航代码触发过滤器(从控制器呈现部分视图。)
【问题讨论】:
-
让 IDisposable 实现执行该类的一些基本工作对我来说很不利。
-
同意,但我正在努力寻找一个更合适的位置来保证调用该函数。有时,UI 请求可能会通过服务层检查错误但这无法得到答复。我确实尝试在 Global.asax 中使用 Application_EndRequest(),[注入] 服务,但这也不太奏效。我愿意接受建议。
-
嗯,解决此问题的一种方法是在控制器获取应用程序错误时调用 LogErrorsToDatabase() 函数,然后清除错误集合中的任何域错误,以便在其他地方获取错误时,相同的错误不会被记录两次。
-
我将建议 EndRequest 作为将错误写入数据库的调用的明显位置。为什么它不起作用?
-
注入 Global.asax 时,似乎所有请求都共享了 ErrorLog 集合。我不确定为什么会这样。错误日志声明为:Bind
().To ().InRequestScope();,因此将其注入 global.asax 的行为似乎在某种程度上使其行为类似于 InSingletonScope?
标签: c# asp.net-mvc-3 ninject idisposable