Search code examples
asp.net-mvc-3autofacaction-filter

ASP.NET MVC 3, Action Filters, and Autofac Dependency Injection


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.

  • Does this mean I'm hosed if I upgrade to MVC 3?
  • If action filters are no longer instanced per request, how will we get request-scoped dependencies into our action filters?

Thanks for any insight.


Solution

  • 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.