I have an MVC4 site that uses both MVC and WebAPI in it. All was going well till I tried to change my classes to have a cross cutting AOP class that would help with caching data. I am now finding that when I call a method that does not have the InterceptAttribute on it, it will crash because Ninject didn't inject with a parameter, and it fails.
My BLL class looks like this:
public class FooBLL
{
#region Private Variables
private readonly IDAL _context;
#endregion
#region Constructor
public Foo(IDAL context)
{
_context = context;
}
#endregion
#region Public Methods
public List<Bar> GetAllBars()
{
return _context.GetAllBars();
}
public List<Bar> GetTwoBars()
{
return _context.GetTwoBars();
}
#endregion
}
My WebApi Controller looks like this:
public class FooController : ApiController
{
#region Private Variables
private readonly FooBLL _fooBll;
#endregion
#region Constructor
public FooController(FooBLL fooBll)
{
_fooBll = fooBll;
}
#endregion
#region Public Methods
#region Estimate Types
#region Get
public List<Bar> GetAllBars()
{
return _fooBll.GetAllBars();
}
public List<Bar> GetTwoBars()
{
return _fooBll.GetTwoBars();
}
#endregion
#endregion
#endregion
}
In my Website, I created the following Ninject classes for resolving the controllers:
public class NinjectRegistrations : NinjectModule
{
public override void Load()
{
Kernel.Bind<IDAL>().To<DAL>().InSingletonScope();
}
}
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver, System.Web.Mvc.IDependencyResolver
{
private readonly IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(this.kernel.BeginBlock());
}
}
public class NinjectDependencyScope : IDependencyScope
{
private IResolutionRoot resolver;
internal NinjectDependencyScope(IResolutionRoot resolver)
{
Contract.Assert(resolver != null);
this.resolver = resolver;
}
public void Dispose()
{
var disposable = this.resolver as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
this.resolver = null;
}
public object GetService(Type serviceType)
{
if (this.resolver == null)
{
throw new ObjectDisposedException("this", "This scope has already been disposed");
}
return this.resolver.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
if (this.resolver == null)
{
throw new ObjectDisposedException("this", "This scope has already been disposed");
}
return this.resolver.GetAll(serviceType);
}
}
In Global.asax I then register this resolver:
NinjectHelper.Kernel = new StandardKernel(modules);
var ninjectResolver = new NinjectDependencyResolver(NinjectHelper.Kernel);
DependencyResolver.SetResolver(ninjectResolver); // MVC
GlobalConfiguration.Configuration.DependencyResolver = ninjectResolver; // Web API
//Register Filter Injector
GlobalConfiguration.Configuration.Services.Add(typeof(System.Web.Http.Filters.IFilterProvider), new NinjectWebApiFilterProvider(NinjectHelper.Kernel));
Things were fine till I added the attribute Cache using Ninject.Extensions.Interception.Attributes.InterceptAttribute.
The class now looks like this (note that I added a parameterless constructor and marked one of the methods as virtual, these are both required for the Interception to work):
public class FooBLL
{
#region Private Variables
private readonly IDAL _context;
#endregion
#region Constructor
public Foo(IDAL context)
{
_context = context;
}
public Foo()
{
}
#endregion
#region Public Methods
public List<Bar> GetAllBars()
{
return _context.GetAllBars();
}
[Cache(DefaultTimeoutMinutes = 20)]
public virtual List<Bar> GetTwoBars()
{
return _context.GetTwoBars();
}
#endregion
}
Now on the WebAPI controller, when I call GetToBars(the method with the Intercept Attribute), everything still works fine.
However, when I call GetAllBars(the method that doesn't have the Intercept Attribute), I fail with an exception that _context is null.
Any help would be greatly appreciated.
Ben