2

I'm trying to clean up the default implementation of AccountController.cs that comes out of the box in the new MVC5/Owin security implementation. I have modified my constructor to look like this:

private UserManager<ApplicationUser> UserManager;
public AccountController(UserManager<ApplicationUser> userManager)
{
    this.UserManager = userManager;
}

Also, I have created a lifetime manager for Unity that looks like this:

 public class HttpContextLifetimeManager<T> : LifetimeManager, IDisposable
    {
        private HttpContextBase _context = null;
        public HttpContextLifetimeManager()
        {
            _context = new HttpContextWrapper(HttpContext.Current);
        }
        public HttpContextLifetimeManager(HttpContextBase context)
        {
            if (context == null)
                throw new ArgumentNullException("context");
            _context = context;
        }
        public void Dispose()
        {
            this.RemoveValue();
        }
        public override object GetValue()
        {
            return _context.Items[typeof(T)];
        }
        public override void RemoveValue()
        {
            _context.Items.Remove(typeof(T));
        }
        public override void SetValue(object newValue)
        {
            _context.Items[typeof(T)] = newValue;
        }
    }

I'm not sure how to write this in my UnityConfig.cs, but this is what I have so far:

container.RegisterType<UserManager<ApplicationUser>>(new HttpContextLifetimeManager(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new RecipeManagerContext()))));

I did find another example (using AutoFac) that does it this way:

container.Register(c => new UserManager<ApplicationUser>(new UserStore<ApplicationUser>( new RecipeManagerContext())))
                .As<UserManager<ApplicationUser>>().InstancePerHttpRequest();

How would I translate the above statement using Unity IoC lifetime management?

Hao Kung
  • 28,040
  • 6
  • 84
  • 93
Kyle B.
  • 5,737
  • 6
  • 39
  • 57

1 Answers1

4

Your approach where the UserManager is registered for specific lifetime is correct. However, I don't understand why it even compiles, since your HttpContextLifetimeManager expects the HttpContext as a parameter.

Another issue is that your implementation is wrong. The parameterless constructor takes current http context, however you rather want the lifetime manager to use the context the instance is created on rather the one the type is registered on. If the parameterless constructor is used, this could lead to http context mismatch issues.

First, change your implementation to

public class HttpContextLifetimeManager : LifetimeManager
{
 private readonly object key = new object();

 public override object GetValue()
 {
     if (HttpContext.Current != null && 
         HttpContext.Current.Items.Contains(key))
         return HttpContext.Current.Items[key];
     else
         return null;
 }

 public override void RemoveValue()
 {
     if (HttpContext.Current != null)
         HttpContext.Current.Items.Remove(key);
 }

 public override void SetValue(object newValue)
 {
     if (HttpContext.Current != null)
         HttpContext.Current.Items[key] = newValue;
 }
}

and then register your type

container.RegisterType<UserManager<ApplicationUser>>( new HttpContextLifetimeManager() );
Wiktor Zychla
  • 47,367
  • 6
  • 74
  • 106
  • How would I think instantiate the object inside the AccountController passing along the DbContext? – Kyle B. Apr 06 '14 at 16:45
  • 1
    Create your own constructor factory that uses unity, http://stackoverflow.com/questions/14649545/how-to-inject-constructor-in-controllers-by-unity-on-mvc-4 Unity will take care of resolving complete object graph. – Wiktor Zychla Apr 06 '14 at 16:49
  • The example you have linked shows how DI works when using an interface, which I already understand. I'm looking to how I can instruct Unity to see what you see ObjectType to create X instance of that object. Look at the line using Autofac above and note that it is passing in constructor parameters. – Kyle B. Apr 07 '14 at 17:52
  • 1
    `container.RegisterType>( new InjectionFactory( c => new UserManager(new UserStore( new RecipeManagerContext())), new HttpContextLifetimeManager() );` – Wiktor Zychla Apr 07 '14 at 18:10
  • You are awesome, thanks. I had to switch it so HttpContextLifetimeManager() was the first parameter to RegisterType, but it works and is just what I was looking for. Checked my work and everything looks good. Much appreciated. – Kyle B. Apr 07 '14 at 18:42
  • AFAIK in OWIN there is no static HttpContext anymore. How do you do this without a static HttpContext for OWIN then? – Isaac Llopis May 05 '15 at 13:12
  • @IsaacLlopis: does this help? http://stackoverflow.com/questions/28227078/data-caching-per-request-in-owin-application/28242568#28242568 – Wiktor Zychla May 05 '15 at 15:14