I\'ve been playing with the DI support in ASP.NET MVC RC2.
I have implemented session per request for NHibernate and need to inject ISession
into my \"Unit
Thought I would come back and provide the solution.
As @Thomas pointed out above, Action Filters are now cached in MVC 3. This means that if you inject an object with an intended short life time (e.g. http request), it's going to be cached.
To fix, instead of injecting an ISession
we inject a Func
. Then each time we need access to ISession we invoke the function. This ensures that even if the ActionFilter is cached, the ISession is scoped correctly.
I had to configure StructureMap like so to inject the "lazy" instance (unfortunately it doesn't inject a lazy instance automatically like it does with Ctor injection):
x.SetAllProperties(p => {
p.OfType>();
});
My updated ActionFilter is below:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class UnitOfWorkAttribute : ActionFilterAttribute {
public Func SessionFinder { get; set; }
public override void OnActionExecuting(System.Web.Mvc.ActionExecutingContext filterContext) {
var session = SessionFinder();
session.BeginTransaction();
}
public override void OnResultExecuted(System.Web.Mvc.ResultExecutedContext filterContext) {
var session = SessionFinder();
var txn = session.Transaction;
if (txn == null || !txn.IsActive) return;
if (filterContext.Exception == null || filterContext.ExceptionHandled)
{
session.Transaction.Commit();
}
else
{
session.Transaction.Rollback();
session.Clear();
}
}
}