On ASP.NET MVC 2 I have an ActionFilterAttribute
called [Transaction]
that starts an NHibernate transaction before executing the action and commits or rolls it back afterward, depending on whether or not an exception was thrown. The ISession
instance is HttpRequestScoped()
and injected by Autofac. It looks like this and works great:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public sealed class TransactionAttribute : ActionFilterAttribute
{
private ITransaction transaction;
public TransactionAttribute()
{
this.Order = 0;
}
public ISession Session
{
get;
set;
}
public override void OnActionExecuted(
ActionExecutedContext filterContext)
{
if (this.Session != null && this.transaction != null)
{
try
{
if (this.transaction.IsActive)
{
if (filterContext.Exception == null)
{
this.transaction.Commit();
}
else
{
this.transaction.Rollback();
}
}
}
finally
{
this.transaction.Dispose();
this.transaction = null;
}
}
}
public override void OnActionExecuting(
ActionExecutingContext filterContext)
{
if (this.Session != null)
{
this.transaction = this.Session.BeginTransaction();
}
}
}
Fantastic. Seems to be a common pattern.
In the ASP.NET MVC 3 notes, I see this little blurb under "Breaking Changes" (emphasis mine):
In previous versions of ASP.NET MVC, action filters were created per request except in a few cases. This behavior was never a guaranteed behavior but merely an implementation detail and the contract for filters was to consider them stateless. In ASP.NET MVC 3, filters are cached more aggressively. Therefore, any custom action filters which improperly store instance state might be broken.
Oops.
Thanks for any insight.
I just asked a similar question on google forums. Here is the link https://groups.google.com/forum/#!topic/autofac/a0qqp2b3WA8
I got the answer:
builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>();
builder.RegisterControllers(Assembly.GetExecutingAssembly()).InjectActionInvoker();
Then you can use property injection in your attributes.