Ninject doesn't resolve dependency (parameterless constructor error) - c#

I'm struggling with enabling Ninject's constructor injection in a Web Service application. Here's the steps I took (Visual Studio 2013):
1) Created a new project with "ASP.NET Web Application" template.
2) Selected an "Empty" application template in the second step of the project creation wizard.
3) In the third step called "Add folders and core references for" selected "Web API"
4) The project is created, now I added a controller of type "Web API 2 Controller - Empty". Added the following code:
using System.Web.Http;
namespace WebApplication1.Controllers
{
public interface IDummy
{
}
public class Dummy : IDummy
{
}
public class DefaultController : ApiController
{
public DefaultController(IDummy dummy)
{
}
[HttpGet]
[Route("")]
public string Index()
{
return "Hello World!";
}
}
}
5) Installed NuGet package: Ninject.Web.WebApi (Ninject integration for WebApi2), now I've found in other threads that to make it work with IIS I need to install Ninject.Web.Common.WebHost package. After this, the NinjectWebCommon.cs file appeared in AppStart. The only edit I did for this file was in RegisterServices method:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IDummy>().To<Dummy>();
}
Now when I try to run the application (locally, just pressing F5 in Visual Studio) I would expect to get the Hello World string in a browser, but instead I get the infamous parameterless constructor error:
which means that the Ninject is for some reason not doing its job I guess. Unfortunately googling for solution was fruitless so far. Anyone can hint me what should I do to make this work? Thanks in advance.

I was able to get this working quite simply by using this solution. You only need to install Ninject.Web.WebApi and then add the following code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http.Dependencies;
using Ninject;
using Ninject.Activation;
using Ninject.Parameters;
using Ninject.Syntax;
internal class NinjectDependencyResolver : NinjectScope, IDependencyResolver
{
private readonly IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
if (kernel == null)
throw new ArgumentNullException("kernel");
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectScope(this.kernel.BeginBlock());
}
}
internal class NinjectScope : IDependencyScope
{
protected IResolutionRoot resolutionRoot;
public NinjectScope(IResolutionRoot kernel)
{
resolutionRoot = kernel;
}
public object GetService(Type serviceType)
{
IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);
return resolutionRoot.Resolve(request).SingleOrDefault();
}
public IEnumerable<object> GetServices(Type serviceType)
{
IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);
return resolutionRoot.Resolve(request).ToList();
}
public void Dispose()
{
IDisposable disposable = (IDisposable)resolutionRoot;
if (disposable != null) disposable.Dispose();
resolutionRoot = null;
}
}
Usage
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
IKernel kernel = new StandardKernel();
kernel.Bind<IDummy>().To<Dummy>();
config.DependencyResolver = new NinjectDependencyResolver(kernel);
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}

Related

An error occurred when trying to create a controller of type 'SaleController'. Make sure that the controller has a parameterless public constructor

I have been following this article:
https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/dependency-injection#dependency-scope-and-controller-lifetime
The error I get is in the title:
Make sure that the controller has a parameterless public constructor.
Basically the Unity code is the same as in the project from microsoft.
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
var container = new UnityContainer();
container.RegisterType<ITrace, Trace>(new HierarchicalLifetimeManager());
container.RegisterType<IUtility, Utility>(new HierarchicalLifetimeManager());
container.RegisterType<IValidator, Validator>(new HierarchicalLifetimeManager());
container.RegisterType<IDeliveryService, DeliveryService>(new HierarchicalLifetimeManager());
container.RegisterType<ISaleService, SaleService>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
I have UnityResolver:
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();
}
Unity should instantiate the controllers using this. My only concern is the db context. I tried searching for ways to register but I got nothing.
As asked here is my dbcontext:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext() : base("DefaultConnection", throwIfV1Schema: false)
{
Configuration.LazyLoadingEnabled = false;
Configuration.ProxyCreationEnabled = false;
Configuration.ValidateOnSaveEnabled = false;
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
I am using Unity for the first time.
In Unity sometimes custom classes that have a specific constructor also require an additional parameter-less constructor (It may be doing nothing but has to exist) like
public UnityResolver(){ }
Afaik this is mostly related to (de)serialization. Not sure why it is required in our specific case .. but that is what the error tries to tell you ;)

How to allow a plugin webAPI to override an existing webAPI

I have a Web API controller, say EmployeeController, which we register using Autofac. Now we create another controller with the same name and route, but with different functionality. When we try to register this new EmployeeController (i.e., Plugin) using Autofac, we would get an exception like
multiple types were found that match the controller named EmployeeController.
My objective is to successfully inject the second controller and override the functionality of the first controller with it.
Project A - > Core Project
namespace Main.API
{
public class EmployeeController : ApiController
{
// Some Logic
}
}
Project B - > Plug-in Project
Later consumer want to override employee controller with same controller name
namespace Plugin.API
{
public class EmployeeController : ApiController
{
// Some Logic
}
}
Autofac
// assemblies contains Main.API.dll & Plugin.API.dll
builder.RegisterApiControllers(assemblies.ToArray()).InstancePerRequest();
In order to implement what you want I would use AOP concept which will make it easier to implement and more powerful.
Castle DynamicProxy project provides AOP concept for .net and can be used by Autofac with the Autofac.Extras.DynamicProxy2 nuget package.
You will have only 1 EmployeeController in your main project
namespace Main.API
{
public class EmployeeController : ApiController
{
public virtual String Get(Int32 id)
{
// Some Logic
}
}
}
and various IInterceptor in your plugin projects :
namespace Plugin
{
public class XEmployeeeControllerInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
if(!invocation.Method.Name == nameof(Core.APi.EmployeeController.Get))
{
return;
}
invocation.Proceed();
// alter return value
invocation.ReturnValue = invocation.ReturnValue + "-intercepted";
}
}
}
Then register things like this:
builder.RegisterApiControllers(assemblies.ToArray())
.InstancePerRequest()
.EnableClassInterceptors();
builder.RegisterAssemblyTypes(assemblies.ToArray())
.As<IInterceptor>();
See Type Interceptors for more information
Using this following code snippet you can override the same name of plugin controller.
public class CustomHttpControllerSelector : DefaultHttpControllerSelector
{
private readonly HttpConfiguration _configuration;
private readonly Lazy<Dictionary<string, HttpControllerDescriptor>> _controllers;
/// <summary>
/// custom http controllerselector
/// </summary>
/// <param name="config"></param>
public CustomHttpControllerSelector(HttpConfiguration config) : base(config)
{
_configuration = config;
_controllers = new Lazy<Dictionary<string, HttpControllerDescriptor>>(InitializeControllerDictionary);
}
/// <summary>
/// GetControllerMapping
/// </summary>
/// <returns></returns>
public override IDictionary<string, HttpControllerDescriptor> GetControllerMapping()
{
return _controllers.Value;
}
private Dictionary<string, HttpControllerDescriptor> InitializeControllerDictionary()
{
var controllers = new Dictionary<string, HttpControllerDescriptor>(StringComparer.OrdinalIgnoreCase);
IAssembliesResolver assembliesResolver = _configuration.Services.GetAssembliesResolver();
IHttpControllerTypeResolver controllersResolver = _configuration.Services.GetHttpControllerTypeResolver();
ICollection<Type> controllerTypes = controllersResolver.GetControllerTypes(assembliesResolver);
foreach (Type t in controllerTypes)
{
var controllerName = t.Name.Remove(t.Name.Length - DefaultHttpControllerSelector.ControllerSuffix.Length);
//Remove Core API Controller and add the Plugin API controller.
if (controllers.Keys.Contains(controllerName) && t.Namespace.Contains("Plugin"))
{
controllers.Remove(controllerName);
}
if (!controllers.Keys.Contains(controllerName))
{
controllers[controllerName] = new HttpControllerDescriptor(_configuration, t.Nam`enter code here`e, t);
}
}
return controllers;
}
}

Resolving dbcontext per request with Unity in WebApi

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?
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.
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

Failing to resolve dependencies with Unity and WebAPI

I'm receiving this odd error when trying to run my controller action in WebAPI:
An error occurred when trying to create a controller of type 'PostController'. Make sure that the controller has a parameterless public constructor.
Resolution of the dependency failed, type = "Example.Controllers.PostController", name = "(none)".
Exception occurred while: Calling constructor Example.Models.PostRepository().
Exception is: NullReferenceException - Object reference not set to an instance of an object.
Here's the problematic code:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
container.RegisterType<IPostRepository, PostRepository>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "ExampleApi",
routeTemplate: "api/{controller}"
);
}
}
public class PostController : ApiController
{
IPostRepository _repository;
public PostController(IPostRepository repository)
{
_repository = repository;
}
public IEnumerable<Post> GetAllProducts()
{
return _repository.GetAll();
}
}
public class PostRepository : IPostRepository
{
private IDbConnection _connection = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);
public IEnumerable<Post> GetAll()
{
return _connection.Query<Post>("SELECT * FROM Posts").ToList();
}
}
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)
{
if (!Container.IsRegistered(serviceType))
{
if (serviceType.IsAbstract || serviceType.IsInterface)
{
return null;
}
}
return Container.Resolve(serviceType);
}
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();
}
}
Does anyone have any idea of what might be the cause? I followed this tutorial: http://www.asp.net/web-api/overview/advanced/dependency-injection
In my experience when I see this message its normally some dependency is not able to be constructed or is missing a dependency. You have IPostRepository registered to PostRepository so that looks good. What about the SqlConnection created in PostRepository? Could you run some test code against just the repository to see if it constructs OK on its own?
Also just in browsing through your code is the check for interfaces blocking your resolution of the IPostRepository in the UnityResolver class?
if (serviceType.IsAbstract || serviceType.IsInterface)
{
return null;
}
The following link has a working project which is based on the same tutorial that you mentioned.
Not much difference to your code except the database will be targeting localdb, and on the UnityResolver there is no checks for Abstract class, which doesn't make any difference I think.
Now, you can use the project as a startup point to add your logic, and know exactly when it fails and why.
hope this helps.

MVC3 + Ninject - How to?

I've just started playing with IoC containers and therefore chosed Ninject.
After several hours of sweat and tears I still cant figure out how to setup my MVC3 application with Ninject.
So far I have:
Global.asax.cs
public class MvcApplication : Ninject.Web.Mvc.NinjectHttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
protected void Application_Start()
{
DependencyResolver.SetResolver(new MyDependencyResolver(CreateKernel()));
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
protected override IKernel CreateKernel()
{
var modules = new [] { new ServiceModule() };
return new StandardKernel(modules);
}
}
ServiceModule.cs
internal class ServiceModule : NinjectModule
{
public override void Load()
{
Bind<IGreetingService>().To<GreetingService>();
}
}
MyDependencyResolver.cs
public class MyDependencyResolver : IDependencyResolver
{
private IKernel kernel;
public MyDependencyResolver(IKernel kernel)
{
this.kernel = kernel;
}
public object GetService(System.Type serviceType)
{
return kernel.TryGet(serviceType);
}
public System.Collections.Generic.IEnumerable<object> GetServices(System.Type serviceType)
{
return kernel.GetAll(serviceType);
}
}
GreetingService.cs
public interface IGreetingService
{
string Hello();
}
public class GreetingService : IGreetingService
{
public string Hello()
{
return "Hello from GreetingService";
}
}
TestController.cs
public class TestController : Controller
{
private readonly IGreetingService service;
public TestController(IGreetingService service)
{
this.service = service;
}
public ActionResult Index()
{
return View("Index", service.Hello());
}
}
Each time I try to load the Index view it either just throws a overflow exception or a HTTP 404 error - If I remove all the Ninject code it works perfectly, whats wrong?
You are mixing an own dependency resolver with the MVC extension. I'd suggest either going with your own dependency resolver or with using the MVC extension but not both. When using the MVC extension you have to use OnApplicationStarted instead of Application_Start.
See http://www.planetgeek.ch/2010/11/13/official-ninject-mvc-extension-gets-support-for-mvc3/ and have a look at the SampleApplication that comes with the source code of the MVC extension https://github.com/ninject/ninject.web.mvc.
Also the fix is not used anymore when you use the current version for the build server: http://teamcity.codebetter.com
UPDATE: The Ninject.MVC3 package continues to be updated and works OOTB against MVC4 RTM (and RC). See this page in the wiki for details.

Categories

Resources