![](/img/trans.png)
[英]How can I unit test controller together with a filter (ASP.NET MVC with autofac)
[英]NHibernate unit of work in ASP.net MVC filter using AutoFac
我正在尝试使用NHibernate和Transactions创建每个请求的工作单元。 我在MVC中有一个全局应用的过滤器。 看起来如下。
public class TransactionAttribute : ActionFilterAttribute
{
private ISession _session;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//Constructor does NOT get run per request.
_session = DependencyResolver.Current.GetService<ISession>();
_session.FlushMode = FlushMode.Commit;
_session.BeginTransaction();
base.OnActionExecuting(filterContext);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Exception == null)
{
_session.Transaction.Commit();
}
else
{
_session.Transaction.Rollback();
}
_session.Dispose();
base.OnActionExecuted(filterContext);
}
}
请注意,我正在使用依赖关系解析程序来获取服务,这意味着它被称为每个请求,而不是被缓存的构造函数,否则我就被认为是。
现在,我的Autofac模块如下所示:
public class AutoFacModule
{
public static IContainer Build()
{
return Build(new ContainerBuilder());
}
public static IContainer Build(ContainerBuilder builder)
{
// You can register controllers all at once using assembly scanning...
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterModule<AutofacWebTypesModule>();
builder.Register(x => NHibernateSetup.CreateSessionFactory()).SingleInstance();
builder.Register(x => x.Resolve<ISessionFactory>().OpenSession()).InstancePerHttpRequest();
//Build Registry.
var returnContainer = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(returnContainer));
return returnContainer;
}
}
因此,据此,我认为每个HTTP请求都会获得一个新的_session。 但这似乎并非如此。 如果我在MVC动作中插入断点并加载页面,等待它到达断点,然后启动一个新选项卡并加载同一页面,等待它到达断点,然后继续进行下去。 我收到一个错误:
Transaction not successfully started
当我尝试提交时。 我相信这是因为第一个请求已经提交了事务。 这似乎是因为两个请求都共享一个ISession,而不是每个请求都唯一。
发布到StackOverflow的行为突然使一切都变得有意义。
因此,由于某种原因,它与全局注册过滤器有关。 因为我有点懒,所以我做了以下工作
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new TransactionAttribute());
}
因此,基本上将每个请求包装在事务中。 在使用DependencyResolver时,这似乎不起作用。 如果我删除了它,然后将属性直接添加到方法上,则一切开始起作用。
作为一个站点说明,我还发现了一种不使用Autofac而无需使用构造函数来注入属性的方法: http ://alexmg.com/filterattribute-property-injection-in-autofac-mvc-3-integration/,这似乎是默认设置autofac下处理过滤器时的方法。
关于这种方法的一些事情让我有些不高兴,因为拥有这样的属性公共似乎有点奇怪(因为除了在构造函数中,任何人都不应设置它)。 但是,它确实使事物能够进行单元测试(尽管我假设依赖关系解析器方式也具有可以进行单元测试的方式)。
因此,现在,我将属性直接放在动作上。 但这可能需要加以考虑,因为诸如日志记录/错误处理之类的可能肯定需要注入的东西会出现在globalfilters集合中?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.