I have just installed the mvc4 rc update and I am trying to build an api application with little luck.
I am using ninject but cant get my controllers to load. I keep getting an error
Type 'Api.Controllers.ConsumerController' does not have a default constructor
I am very new to mvc and using injection so please bear with me.
I havent done anything special to the default binding that is created via nuget
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IConsumerRepository>().To<ConsumerRepository>();
}
}
My controller looks like
private readonly IConsumerRepository _repository;
public ConsumerController(IConsumerRepository repository)
{
_repository = repository;
}
[HttpGet]
public IQueryable<Consumer> Get(Guid id)
{
return _repository.Get(id).AsQueryable();
}
What do I need to do to get the api controllers to work with ninject?
Sorry if this is simple stuff
I tried your suggestion Michael however after changing the the webcommon.cs to this
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IConsumerRepository>().To<ConsumerRepository>();
}
I get an error when
var kernel = new StandardKernel();
is called
Method 'GetFilters' in type 'Ninject.Web.WebApi.Filter.DefaultFilterProvider' from assembly 'Ninject.Web.WebApi, Version=3.0.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7' does not have an implementation.
What am I missing?
I asked Brad Wilson about this and it has changed in MVC4 RC.
GlobalConfiguration.Configuration.ServiceResolver has been moved to GlobalConfiguration.Configuration.DependencyResolver
Use this implementation to create a Ninject DependencyResolver for your Web Api:
https://gist.github.com/2417226
In NinjectWebCommon.cs:
// Register Dependencies
RegisterServices(kernel);
// Set Web API Resolver
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
This generic error message
Type 'Api.Controllers.ConsumerController' does not have a default constructor
can also occur if you do not make your constructor public, or the dependency cannot be resolved by the IoC container maybe because of a missing argument.
The error message is misleading to say the least.
You can install the NuGet package WebApiContrib.IoC.Ninject and add the following line of code to NinjectWebCommon.cs
GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
For someone landing here while searching '...does not have a default constructor' looking for an easy way to debug silently failing configurations:
Remove constructor-injected objects until the constructor can be invoked
For each of the previously injected, now uninitialized objects, invoke using:
ServiceLocator.Current.GetInstance<[OBJ-TYPE]>()
The offending object will cause an ActivationException with a descriptive Message. You'll have something to go for.
Remember to remove call to ServiceLocator post-fix. Ie. this is not a recommendation to use the service locator anti pattern outside debugging.
have you registered the container with the frawework? I prefer using autofac, here is an example of how to use autofac with API. http://alexmg.com/post/2012/03/08/Autofac-ASPNET-Web-API-%28Beta%29-Integration.aspx
Also, Mark Seeman has a good post on DI in general with WebAPI
http://blog.ploeh.dk/2012/03/20/RobustDIWithTheASPNETWebAPI.aspx
From Ploeh:
GlobalConfiguration.Configuration.ServiceResolver.SetResolver(
t => this.container.Kernel.HasComponent(t) ?
this.container.Resolve(t) :
null,
t => this.container.ResolveAll(t).Cast<object>());
The above has to be performed in the global.asax
Hopefully this helps someone else...
I was having the same issue and it was related to me moving class responsible for registering assembly in charge of initializing controllers. Moved out of web into framework project.
Using Autofac but same would apply for other containers.
Was calling:
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
Which works fine when it's within web application, but threw above exception when moved to framework project as the executing assembly no longer contains the controllers.
Instead had to update to:
builder.RegisterApiControllers(Assembly.GetCallingAssembly());
It seems Ninject didn't throw an exception as it generally does when your IOC dependencies aren't quite set up right. Instead it made it look like I hadn't registered the WebAPI dependency resolver which I certainly did. Here was my solution to this problem but from what I've found it could be MANY DIFFERENT types of setup issues. Just re-check everything in the dependency chain. Hopefully it helps someone!
The controller:
public class ContestsController : ApiController
{
//Ninject wouldn't inject this CTOR argument resulting in the error
public ContestsController(IContestEntryService contestEntryService)
{
The dependency:
public class ContestEntryService : IContestEntryService
{
public ContestEntryService(IContestsContext contestsContext)
{
The incorrect configuration:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IContestsContext>()
.To<ContestsContext>()
.InRequestScope();
kernel.Bind(x =>
x.FromAssembliesMatching("MyNameSpace.*")
.SelectAllClasses()
.BindAllInterfaces()
);
The correct configuration:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind(x =>
x.FromAssembliesMatching("MyNameSpace.*")
.SelectAllClasses()
.BindAllInterfaces()
);
kernel.ReBind<IContestsContext>()
.To<ContestsContext>()
.InRequestScope();
Generally Ninject is pretty good about reporting these sorts of errors so I really got thrown for a loop on this one!
I know its an old post, but i found the solution at some link so sharing here. Hope it helps.
http://weblogs.asp.net/hajan/archive/2013/03/16/quick-tip-how-to-make-ninject-work-with-asp-net-web-api.aspx?CommentPosted=true#commentmessage
if any anyone is still having problems, please listen for some reason ninject is not working how we would expect with mvc 4. In your web api, you need to write this code
public DefaultController() : base() { }
This removes the error saying about no default constructor, then when you need to get your data from the get method write this code:
public IEnumerable<YourModelGoesHere> Get()
{
return context.YourData;
}
Keep in mind, you will have to access your db class here as well, for instance:
DefaultConnection context = new DefaultConnection();
just install Ninject.MvcXXX package, where XXX - version of MVC...
I had this error message, too, but it just turned out that one of my interfaces weren't actually implemented by any classes (I forgot to add it to the class declaration).
Related
I've read every Stack Overflow question I can find but to no avail. When I installed the Ninject packages through NuGet, the NinjectWebCommon.cs class was not installed, so I coded up my own (below). I installed Ninject, Ninject.WebCommon, Ninject.Webcommon.Webhost, Ninject.WebApi, Ninject.WebApi.DependencyResolver. However, I am getting the well-known message in my controller that I must have a parameterless controller, which of course I don't want since I want to require DI.
Here's the Ninject class I created:
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new Ninject.WebApi.DependencyResolver.NinjectDependencyResolver(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
//kernel.Load(Assembly.GetExecutingAssembly());
kernel.Bind<IUnitsSL>().To<UnitsSL>();
kernel.Bind<IForecastLogic>().To<ForecastLogic>();
kernel.Bind<IForecastRepositoryAsync>().To<ForecastRepositoryAsync>();
}
}
Here is the controller
namespace ForecastApi.Controllers
{
public class ForecastController : ApiController
{
private IUnitsSL _serviceLayer { get; set; }
private readonly IForecastLogic _forecastLogic;
public ForecastController(IForecastLogic forecastLogic)
{
_forecastLogic = forecastLogic;
_serviceLayer = new UnitsSL();
}
[Route("projection")]
[HttpPost]
public async Task<IHttpActionResult> GetDemandForecast([FromBody]
ProjectionRequestModel model)
{
var retVal = await _forecastLogic.GetDemandForecastData(model);
return Ok(retVal);
}
}
The exact wording of the error message when I test this through Postman is: An error occurred when trying to create a controller of type 'ForecastController'. Make sure that the controller has a parameterless public constructor."
If it helps, I am mocking my unit tests for the business calls and they are working with the Ninject library and Moq. It is the constructor that seems to fail.
TIA
For whatever reason, uninstalling Ninject entirely and reinstalling it (this is version 3.3) solved the problem. Leaving this here in the event that anyone else has a similar issue. I had originally installed
Ninject
Ninject.Web.Common
Ninject.Web.Common.WebHost
Ninject.Web.WebApi
Ninject.Web.WebApi.WebHost
When I uninstalled all of these packages, then re-installed them v3.3 again, the NinjectWebCommon.cs file was added and all worked ok. I can only assume that there was something missing when I rolled my own common file to make up for Ninject not installing it the first go around.
I am trying to learn MVC and I started out with the book Pro ASP.NET MVC by Adam Freeman (5th edition #2013).
In chapter VII I'm trying to follow the example in the book making a small app.
The app fails to load after setting it up and trying to load a list of products.
I'm trying to create a mock implementation of the abstract repository IProductRepository and have Ninject return the mock object whenever it gets a request for an implementation of the IProductRepository interface.
I've searched and looked over other questions/ answers and found nothing that could help solve my problem and let me move forward with studying. This may be basic stuff but I really want to know what and why is not working as it should.
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
}
}
}
This next is my NinjectDependencyResolver class:
public class NinjectDependencyResolver : IDependencyResolver
{
private IKernel kernel;
[Inject]
public NinjectDependencyResolver(IKernel kernelParam)
{
kernel = kernelParam;
AddBindings();
}
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
private void AddBindings()
{
var mock = new Mock<IProductsRepository>();
mock.Setup(m => m.Products).Returns(new List<Product>
{
new Product { Name = "Fotball", Price = 25 },
new Product { Name = "Surf Board", Price = 45 },
new Product { Name = "Running Shoes", Price = 95 }
});
kernel.Bind<IProductsRepository>().ToConstant(mock.Object);
}
}
And this is my controller class:
public class ProductController : Controller
{
private IProductsRepository repository;
public ProductController(IProductsRepository productRepository)
{
repository = productRepository;
}
public ViewResult List()
{
return View(repository.Products);
}
The error I get is the following:
Error activating IProductsRepository
No matching bindings are available, and the type is not self-bindable.
Activation path:
2) Injection of dependency IProductsRepository into parameter productRepository of constructor of type ProductController.
1) Request for ProductController.
Suggestions:
1) Ensure that you have defined a binding for IProductsRepository.
2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
3) Ensure you have not accidentally created more than one kernel.
4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.
5) If you are using automatic module loading, ensure the search path and filters are correct.
OK, so it seems that I had another error which said:
Found conflicts between different versions of the same dependent assembly that could not be resolved
I had installed the specific versions of Ninject, Ninject.Web.Common, Ninject.MVC3, Moq and the other packages as specified by the book author.
After reading the error in the build output I tried updating all installed packages to the latest versions, rebuild the project and it all worked just fine!
I know there are many posts very similar to this one. However, I have been through them and have not been able to find a solution to my problem.
I am implementing OAth authentication using OWIN into a previous project which utilises Ninject for dependency injection.
To implement OATH using OWIN switched from the original Global.asax Application_Start configuration method to creating a Start.cs file/class which is used to configure OWIN.
The problem I am facing is that no matter what implementation I try upon running the code, an API request always returns the error "Make sure that the controller has a parameterless public constructor".
Please can some one shed some light on why neither of the below approaches work?
My first attempt at resolving the issue was to use app.UseNinjectMiddleware with app.UseNinjectWebApi. Secondly I tried a NinjectDependencyResolver which has been mentioned on many previous posts. Link to similar post.
Below is the code contining both implementations.
public class Startup
{
public void Configuration( IAppBuilder app )
{
var config = new HttpConfiguration();
var kernel = NinjectWebCommon.CreateKernel();
// Using this and UseNinjectWebAPI
app.UseNinjectMiddleware( () => kernel );
ConfigureOAuthTokenGeneration( app );
ConfigureWebApi( config );
app.UseCors( Microsoft.Owin.Cors.CorsOptions.AllowAll );
WebApiConfig.Register( config );
app.UseNinjectWebApi( config );
// Also tried this ( when the following lines are uncommented UseNinjectMiddleware and useNinjectWebApi is commented )
// This causes "Make sure that the controller has a parameterless public constructor" error
//GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver( kernel );
//app.UseWebApi( config );
}
private void ConfigureOAuthTokenGeneration( IAppBuilder app )
{
// Configure the db context and user manager to use a single instance per request
app.CreatePerOwinContext( ApplicationDbContext.Create );
app.CreatePerOwinContext<ApplicationUserManager>( ApplicationUserManager.Create );
// Plugin the OAuth bearer JSON Web Token tokens generation and Consumption will be here
}
private void ConfigureWebApi( HttpConfiguration config )
{
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
}
}
Here is my NinjectWebCommon class
//[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(TimeUp.Web.Api.App_Start.NinjectWebCommon), "Start")]
//[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(TimeUp.Web.Api.App_Start.NinjectWebCommon), "Stop")]
namespace Shopping
{
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule( typeof( OnePerRequestHttpModule ) );
DynamicModuleUtility.RegisterModule( typeof( NinjectHttpModule ) );
bootstrapper.Initialize( CreateKernel );
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
public static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
kernel.Bind<Func<IKernel>>().ToMethod( ctx => () => new Bootstrapper().Kernel );
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices( kernel );
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices( IKernel kernel )
{
}
}
}
Thanks in advanced
I finally solved the problem, the solution was to use the original NinjectWebCommon class that came with the Ninject.Web.Common library. This class's start method fires before Startup.Configuration so can be used with this Dependency Resolver by retiring it through the bootstrapper. Here is my working configuration.
public void Configuration( IAppBuilder app )
{
var config = new HttpConfiguration();
config.DependencyResolver = new NinjectResolver( new Ninject.Web.Common.Bootstrapper().Kernel );
WebApiConfig.Register( config );
app.UseWebApi( config );
}
I'm using NinjectWebCommon to perform the injections in my controllers. I installed the package via Nuget and he created the NinjectWebCommon.cs in my App_Start as it says in the own documentation. I need to know why it does not work as it should, because I follow the documentation step by step. Follows some snippets:
NinjectWebCommon.cs:
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
//kernel.Load(AppDomain.CurrentDomain.GetAssemblies());
kernel.Bind<IFooService>().To<FooService>();
}
}
Controller:
public class FooController : Controller
{
private readonly IFooService fooService;
public FooController(IFooService fooService)
{
this.fooService = fooService;
}
public ActionResult Index()
{
return View(this.fooService.All());
}
}
This generates this error:
Error activating IFooService No matching bindings are available, and
the type is not self-bindable. Activation path:
2) Injection of
dependency IFooService into parameter fooService of constructor of
type FooController
1) Request for FooController
Suggestions:
1) Ensure that you have defined a binding for
IFooService.
2) If the binding was defined in a module, ensure that
the module has been loaded into the kernel.
3) Ensure you have not
accidentally created more than one kernel.
4) If you are using
constructor arguments, ensure that the parameter name matches the
constructors parameter name.
5) If you are using automatic module
loading, ensure the search path and filters are correct.
Use IoC to resolve instances, but it works only in my HomeController, if I change to another controller using EXACTLY the same code (with the IoC), it generates the error again. Follows the code using the IoC.
using IoC:
private readonly IFooService fooService;
public HomeController()
{
this.fooService = IoC.Instance.Resolve<IFooService>();
}
public ActionResult Index()
{
ViewBag.MyFoos = this.fooService.All();
return View();
}
generates this error:
No matching bindings are available, and the type is not self-bindable.
Error activating IFooService
No matching bindings are available,
and the type is not self-bindable.
Activation path:
1) Request for IFooService
Suggestions:
1) Ensure
that you have defined a binding for IFooService.
2) If the binding
was defined in a module, ensure that the module has been loaded into
the kernel.
3) Ensure you have not accidentally created more than one
kernel.
4) If you are using constructor arguments, ensure that the
parameter name matches the constructors parameter name.
5) If you are
using automatic module loading, ensure the search path and filters are
correct.
Are you sure you have a binding for ISetorService? I don't see one in the code you've posted.
I solved the problem by loading all "NinjectModule" of my application hierarchy.
I thought it was sufficient loading only the main module, then created another statico method within the "NinjectWebCommon" just to separate responsibilities and organizing the code. Below is the code used:
var kernel = new StandardKernel(new Repository(), new Service(), new ValidationAndBusinessRules());
which carry all their Repositories, Services and Validators in creating the Kernel.
private static void RegisterObrigatoryServices(IKernel kernel)
{
kernel.Bind<IIdentityProvider>().To<ServiceIdentityProvider>();
kernel.Bind<Guid>().ToMethod(ctx => default(Guid)).Named("CurrentProcessId");
kernel.Bind<ISession>().ToMethod(ctx =>
{
SessionPoolManager.Update();
Guid processId = kernel.Get<Guid>("CurrentProcessId", new Parameter[] { });
if (processId == default(Guid))
{
return SessionFactoryBuilder.SessionFactory(kernel.Get<IIdentityProvider>()).OpenSession();
}
else
{
ISession session = SessionPoolManager.Get(processId);
if (session == null)
{
session = SessionFactoryBuilder.SessionFactory(kernel.Get<IIdentityProvider>()).OpenSession();
SessionPoolManager.Register(processId, session);
}
return session;
}
});
}
method created by me within the NinjectWebCommon as mentioned above, only to record the required dependencies.
All this code is basically native and has been inserted into the Nuget Ninject.MVC4 package (installed via Package Manager Console within Visual Studio). This package inserts a class in App_Start directory called "NinjectWebCommon," and it is that I made these changes.
the controler is set to send the package documentation, as follows:
public class HomeController : Controller
{
private readonly IFooService fooService;
public HomeController(IFooService fooService)
{
this.fooService = fooService; //Daqui para frente é possível usar normalmente o service.
}
}
My asp.net WebApi project comprises of multiple assemblies for Services, Core and Data Access. In an attempt to use Ninject as my DI container in the project, I added Ninject.Web.Common package from NuGet. Then, I Implemented IDependencyResolver as:
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
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
{
IResolutionRoot resolver;
public NinjectDependencyScope(IResolutionRoot resolver)
{
this.resolver = resolver;
}
public object GetService(System.Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has been disposed");
var resolved = this.resolver.Get(serviceType);
return resolved;
}
public System.Collections.Generic.IEnumerable<object> GetServices(System.Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has been disposed");
return this.resolver.GetAll(serviceType);
}
public void Dispose()
{
IDisposable disposable = resolver as IDisposable;
if (disposable != null)
disposable.Dispose();
resolver = null;
}
}
Here is my Ninject.Web.Common.cs.
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind(x =>
x.FromAssembliesInPath(AppDomain.CurrentDomain.RelativeSearchPath)
.SelectAllIncludingAbstractClasses()
.BindDefaultInterface()
.Configure(config => config.InSingletonScope()));
//kernel.Bind(x =>
// {
// x.FromAssembliesMatching("*")
// .SelectAllClasses()
// .BindDefaultInterface()
// .Configure(b => b.InTransientScope());
// });
//kernel.Load()
//kernel.Bind<ISecurityService>().To<SecurityServiceImplementation>();
//kernel.Bind(x => x
// .FromAssembliesMatching("*")
// .SelectAllClasses()
// .BindDefaultInterface());
//.Configure(b => b.InTransientScope()));
//kernel.Load("*.dll");
}
}
exception is
[ActivationException: Error activating IHostBufferPolicySelector
No matching bindings are available, and the type is not self-bindable.
Activation path:
1) Request for IHostBufferPolicySelector
I have used various registrations (commented out) but none work. The break point in NinjectWebCommon.cs -> CreateKernel() method is hit and so does the break point in GetService(System.Type serviceType) method. AppDomain.CurrentDomain.RelativeSearchPath resolves to the bin directory of the app and it contains all the dlls including System.Web.Http.dll which contains the IHostBufferPolicySelector type.
How can I properly use the Ninject.Extensions.Conventions to setup the kernel for type resolution?
From the hints in the answer by Remo and comment by Filip along with a significant amount of debugging time, I found out the use of this.resolver.Get(serviceType) instead of this.resolver.TryGet(serviceType) in GetService() implementation was the culprit in my situation.
I plan a detailed blog post about this but the short of it is that once we have the NinjectDependencyResolver plugged into MVC using the line:
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
and we don't define Framework level dependency bindings (e.g. IHostBufferPolicySelector etc.), an exception is raised by the Get() method for some framework level dependencies when they are not resolved through Ninject. Using TryGet() does not raise an exception and the framework falls back to default dependencies for unresolved (a.ka. null) dependencies like IHostBufferPolicySelector. So, the options are
Use the TryGet() method to resolve dependencies.
Wrap Get in Try/Catch and discard the exception.
Try this post. Instead of catching the Ninject exception, catch the exception for all WebApi calls. http://blog.greatrexpectations.com/2013/05/15/exception-handling-for-web-api-controller-constructors/
In the stacktrace, the constructor where the exception occured would be visible.
There is no class HostBufferPolicySelector so there in no class for which IHostBufferPolicySelector is the default interface. You may try BindAllInterfaces or BindDefaultInterfaces.