I'm having difficulty using the Ninject InSingletonScope binding with Api RC Web. Regardless of how I create the binding, it looks like Web Api handles the area / lifetime instead of Ninject.
I tried several options for connecting Ninject. The most common one is that here's the answer: Associating ASP.NET web APIs with ninject
I also tried this version: http://www.peterprovost.org/blog/2012/06/19/adding-ninject-to-web-api/
In both cases, I literally create the Web Api project out of the box, and then add the Ninject packages, as described in any post. Finally, I add the Resolver and Scope classes, for example, for the StackOverflow version:
public class NinjectDependencyScope : IDependencyScope { private IResolutionRoot resolver; internal NinjectDependencyScope(IResolutionRoot resolver) { Contract.Assert(resolver != null); this.resolver = resolver; } public void Dispose() { IDisposable disposable = resolver as IDisposable; if (disposable != null) disposable.Dispose(); resolver = null; } public object GetService(Type serviceType) { if (resolver == null) throw new ObjectDisposedException("this", "This scope has already been disposed"); return resolver.TryGet(serviceType); } public IEnumerable<object> GetServices(Type serviceType) { if (resolver == null) throw new ObjectDisposedException("this", "This scope has already been disposed"); return resolver.GetAll(serviceType); } }
and
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver { private IKernel kernel; public NinjectDependencyResolver(IKernel kernel) : base(kernel) { this.kernel = kernel; } public IDependencyScope BeginScope() { return new NinjectDependencyScope(kernel.BeginBlock()); } }
Then NinjectWebCommon looks like this:
using System.Web.Http; using MvcApplication2.Controllers; [assembly: WebActivator.PreApplicationStartMethod(typeof(MvcApplication2.App_Start.NinjectWebCommon), "Start")] [assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(MvcApplication2.App_Start.NinjectWebCommon), "Stop")] namespace MvcApplication2.App_Start { using System; using System.Web; using Microsoft.Web.Infrastructure.DynamicModuleHelper; using Ninject; using Ninject.Web.Common; public static class NinjectWebCommon { private static readonly Bootstrapper bootstrapper = new Bootstrapper();
The ILogger and Logger objects do nothing, but illustrate the problem. Logger does Debug.Writeline so that I can see when it was created. And every page update shows that it is updated per call, not the singleton I was hoping for. Here is the controller using Logger:
public class ValuesController : ApiController { private readonly ILogger _logger; public ValuesController(ILogger logger) { _logger = logger; _logger.Log("Logger created at " + System.DateTime.Now.ToLongTimeString()); } // GET api/values public IEnumerable<string> Get() { return new string[] { "value1", "value2" }; } // GET api/values/5 public string Get(int id) { return "value"; } // POST api/values public void Post(string value) { } // PUT api/values/5 public void Put(int id, string value) { } // DELETE api/values/5 public void Delete(int id) { } }
When I add trace information to the kernel creation, it seems that the kernel is created only once. So ... what can't I see? Why is the singlet not saved?