16

I am struggling to make this work. I've got Unity and Unity.AspNet.WebApi packages (v 3.5.1404) installed and below activation code which came with the packages

public static class UnityWebApiActivator
{
    /// <summary>Integrates Unity when the application starts.</summary>
    public static void Start() 
    {
        var container = UnityConfig.GetConfiguredContainer();
        var resolver = new UnityHierarchicalDependencyResolver(container);

        GlobalConfiguration.Configuration.DependencyResolver = resolver;

        // DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
    }

    /// <summary>Disposes the Unity container when the application is shut down.</summary>
    public static void Shutdown()
    {
        var container = UnityConfig.GetConfiguredContainer();
        container.Dispose();
    }
}

and my type registration looks like this:

 public static void RegisterTypes(IUnityContainer container)
        {
            container.RegisterType<IAuditService, AuditService>(
                new PerThreadLifetimeManager(),
                new InjectionConstructor(new SecurityDbContext()));
        }

So far I've tried PerThreadLifetimeManager and TransientLifetimeManager with no success. I've also got the Unity.Mvc package and tried using the PerRequestLifetimeManager as suggested by msdn but no luck. It always gives me the same instance of dbcontex.

I rather do not include any MVC dependency as this is purely WebApi but when I try to use Unity.Mvc, I ended up some http runtime errors too.

Anyone has a good suggestion/example to resolve dbcontext per request with Unity in WebApi, preferably without any mvc dependency?

Otake
  • 874
  • 3
  • 8
  • 21

2 Answers2

14

The way I was injecting db context was the problem here. Unity remembers the instance created and injects the same instance for all new AuditService instance created. I simply needed to resolve the db context as below.

container.RegisterType<DbContext, SecurityDbContext>(new PerThreadLifetimeManager());

PerThreadLifetimeManager did the work and it should be fine considering each web requests will be served by a different thread.

Otake
  • 874
  • 3
  • 8
  • 21
  • Not able to get this 'SecurityDbContext'. Is this a self defined a class which is inheriting Dbcontext class? – Piyush May 16 '16 at 19:07
  • Yes SecurityDbContext inherits the DbContext and it is where I add the EF mappings by overriding OnModelCreating method. – Otake May 22 '16 at 13:02
  • @Otake how is it declared on the Controller so that it works? Tks – Pascal Aug 11 '16 at 21:22
  • @Pascal, It depends how you wanna go about accessing DB from controllers. In my case, I have a service class called SecurityService which takes in SecurityDbContext through constructor, and controller takes in ISecurityService through constructor which again is resolved by Unity as SecurityService. As a direct approach, you could have SecurityDbContext as part of controller constructor parameter but unless it is a small and simple app, I would not advise this. Hope this helps. – Otake Aug 12 '16 at 14:00
  • @Otake Somebody helped me in this answer today. http://stackoverflow.com/questions/38907889/unable-to-inject-dbcontext-into-my-web-api-2-controller-with-unity/38910440 . My problem was multiple constructors. It's working now. – Pascal Aug 12 '16 at 14:41
  • 15
    Using the `PerThreadLifetimeManager` in a web application is a [really, really bad idea](https://stackoverflow.com/questions/14591422/why-is-perthreadlifetimemanager-used-in-this-example/14592419). – Steven Oct 08 '16 at 10:03
  • It has been sometime so I am not sure if any other scope (PerRequest etc...) was available in unity at the time. Sure it is bad, I agree with your post. I used structuremap at the end. – Otake Oct 18 '16 at 15:40
3

I managed to resolve per request by declaring my custom UnityResolver's class within the WebApiConfig class. The UnityResolver class uses the HttpConfiguration class assuming you're using an OWIN context.

public static void Register(HttpConfiguration config)
        {    
            // Web API configuration and services
            var _container = new UnityContainer();
            DependencyConfiguration.ConfigureContainer(_container);
            config.DependencyResolver = new UnityResolver(_container);
         }

The ConfigureContainer class is simply a class where I declare my IOC dependencies as shown below:

private static void RegisterReleaseEnv(IUnityContainer container)
        {
            //Repository Registration
            container             
              .RegisterType(typeof(IRepository<>), typeof(GenericRepository<>), new HierarchicalLifetimeManager());

        }

It is very important that you use the HierarchicalLifetimeManager lifetime manager so that you get a new instance per request.

The UnityResolver class then looks like this:

public class UnityResolver : IDependencyResolver
    {
        protected IUnityContainer container;

        public UnityResolver(IUnityContainer container)
        {
            if (container == null)
            {
                throw new ArgumentNullException("container");
            }
            this.container = container;
        }

        public object GetService(Type serviceType)
        {
            try
            {
                return container.Resolve(serviceType);
            }
            catch (ResolutionFailedException)
            {
                return null;
            }
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            try
            {
                return container.ResolveAll(serviceType);
            }
            catch (ResolutionFailedException)
            {
                return new List<object>();
            }
        }

        public IDependencyScope BeginScope()
        {
            var child = container.CreateChildContainer();
            return new UnityResolver(child);
        }

        public void Dispose()
        {
            container.Dispose();
        }
    }

I then get a new DB Context using a Generic Repistory as shown below:

public class GenericRepository<TEntity> : IRepository<TEntity>, IDisposable where TEntity : class
{
    internal BackendContainer context;
    internal DbSet<TEntity> dbSet;

    public GenericRepository(BackendContainer context)
    {
        this.context = context;
        this.dbSet = context.Set<TEntity>();
    }

    public GenericRepository()
        : this(new BackendContainer())
    {
    }


    public virtual IQueryable<TEntity> All()
    {
        return dbSet.AsQueryable();
    }
}

Because of the Unity Resolver, the Generic Repository is instantiated per request and so is the DbContext (BackendContainer).

I hope this helps.

For more information: http://www.asp.net/web-api/overview/advanced/dependency-injection

David Tansey
  • 5,813
  • 4
  • 35
  • 51
Shaun Grech
  • 351
  • 3
  • 5