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.
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.
AutoFac is an Inversion of Control container that resolves dependencies of an application. This means that it also is a dependency injection framework.
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.
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.
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.
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With