Action Filter Dependency Injection in ASP.NET MVC 3 RC2 with StructureMap

前端 未结 3 2451
广开言路
广开言路 2021-02-20 11:09

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

相关标签:
3条回答
  • 2021-02-20 11:22

    Did you implement your own IDependencyResolver that uses StructureMap? It seems like you must not have, because you set the session to be HttpContext scoped and yet you are seeing separate sessions during the same request.

    0 讨论(0)
  • 2021-02-20 11:31

    I don't know if it would help but with MVC 3 action filters are now cached instead of being instantiated new at the beginning of every request. So if you're injecting dependencies something in the constructor it won't work well. Could you post your implementation of FilterAttributeFilterProvider ?

    0 讨论(0)
  • 2021-02-20 11:36

    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<ISession>. 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<Func<ISession>>();
                });
    

    My updated ActionFilter is below:

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
    public class UnitOfWorkAttribute : ActionFilterAttribute {
    
        public Func<ISession> 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();
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题