Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 888
Nicholas Piasecki Avatar asked Jan 14 '11 21:01

Nicholas Piasecki


People also ask

Does MVC support dependency injection?

The Dependency Injection (DI) Design PatternThe Dependency Resolver in ASP.NET MVC can allow you to register your dependency logic somewhere else (e.g. a container or a bag of clubs). The advantages of using Dependency Injection pattern and Inversion of Control are the following: Reduces class coupling.

What is AutoFac dependency injection?

AutoFac is an Inversion of Control container that resolves dependencies of an application. This means that it also is a dependency injection framework.

What is the need of action filters in ASP.NET MVC?

ASP.NET MVC provides Action Filters for executing filtering logic either before or after an action method is called. Action Filters are custom attributes that provide declarative means to add pre-action and post-action behavior to the controller's action methods.

How AutoFac is implemented in MVC?

To get Autofac integrated with MVC you need to reference this MVC integration NuGet package, register your controllers, and set the dependency resolver. You can optionally enable other features as well. If you are using MVC as part of an OWIN application, you may be interested in the ASP.NET MVC OWIN integration.


2 Answers

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.

like image 183
dmonlord Avatar answered Nov 15 '22 10:11

dmonlord


Oh yuck.... Nicholas, you might need to store your ISession and Transaction in HttpContext.Items, which you should be able to get to via the ActionExecutedContext/ActionExecutingContext (perhaps setting it in the OnActionExecuting event handler), instead of keeping them in instance members. Either that, or you could call a ServiceLocator inside your filter to grab them for you (also yuck).

Now I have to go look through my MVC 3 code and see if I have any similar problems myself!

like image 21
James Nail Avatar answered Nov 15 '22 11:11

James Nail