Unity.WebApi | Make sure that the controller has a parameterless public constructor

24,644

Solution 1

In my experience there's 2 different scenarios when this occur.

1. Make sure that all parameters in the Service constructor can be resolved. Does it have any dependencies that you haven't registered?

Make sure that the controller has a parameterless public constructor in Unity

2. Make sure to register Unity with Web API. Like so:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Routes and other stuff here...

        var container = IocContainer.Instance; // Or any other way to fetch your container.
        config.DependencyResolver = new UnityDependencyResolver(container);
    }
}

Examples here:

Injecting Dependency into Web API Controller

http://codeclimber.net.nz/archive/2015/02/20/Using-Entity-Framework-within-an-Owin-hosted-Web-API-with.aspx

EDIT 1:

As @NightOwl888 mentioned in the comments, you should not dispose the container. The registrations are registered on the container, and when the container is disposed it will not know how to resolve the dependencies. It may result in the error you are seeing.

EDIT 2:

Since you're using Owin you should be able to do something like this:

    public void Configuration(IAppBuilder appBuilder) 
    { 
      // Configure Web API for self-host. 
      HttpConfiguration config = new HttpConfiguration();
      config.DependencyResolver = new UnityDependencyResolver(
          UnityConfig.GetConfiguredContainer());

      config.Routes.MapHttpRoute( 
                    name: "DefaultApi", 
                    routeTemplate: "api/{controller}/{id}", 
                    defaults: new { id = RouteParameter.Optional } 
                ); 

      appBuilder.UseWebApi(config); 
    }

And update your UnityConfig to this:

    public static class UnityConfig {
       public static IUnityContainer GetConfiguredContainer() {
            var container = new UnityContainer();
            // Register controller
            container.RegisterType<MyController>();

            // Register interface
            container.RegisterType<IService, Service>();

            //This is done in Startup instead.
            //GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
            return container;
    }
}

From this source: How to use DI container when OwinStartup

http://damienbod.com/2013/10/01/self-host-webapi-with-owin-and-unity/

In this method, the HttpConfiguration.DependencyResolver is set to a UnityDependencyResolver instance. This is required so that contructor injection can be used in the webApi controllers. The UnityDependencyResolver class is exactly the same as the Unity.WebApi.UnityDependencyResolver class. Unity.WebApi is not used because this is a self hosted OWIN application.

Solution 2

Set the DependencyResolver to the HttpConfiguration you created at Startup, not GlobalConfiguration.Configuration and make sure all your services constructor are public, hope this helps

Solution 3

One more possible investigation path and cause for this issue. I set breakpoints on my global exception handler and looked into the nested exception property on my exception instance. I got the error does not have an accessible constructor which was true because the type I wanted to inject did have a private constructor (I was refactoring a singleton).

Solution 4

I'm using Unity of version 4.0.1 and in my case the nested dependency Repository have had two public constructors and Unity hasn't managed to choose the parameterless constructor.

Thus, I've just specified the other one as protected to quickly solve the issue.

    public Repository() : this( ... ) { ... }

    // if need to make public, make sure that the dependency injection container
    // will choose the parameterless constructor;
    // Unity has had issues with that by default
    protected Repository(DbContext context) : base() { ... }

IMO, Unity could have managed to find the "possible to call" constructor - as it had no DbContext (or any derived context) registered.

Please note that by default Unity chooses a constructor with the maximum number of arguments.

So yes, it's also possible to decorate the proper constructor with InjectionConstructorAttribute as it's described here and here - but I even don't have a Unity reference in my data access layer (and don't want to).

Please tell me if such behavior has changed in the later versions.

Solution 5

Be sure that any nested types which are also injected are being resolved correctly. You will get error message on the controller level even if nested types are resolved incorrectly.

Share:
24,644
Jason McKindly
Author by

Jason McKindly

Updated on February 18, 2020

Comments

  • Jason McKindly
    Jason McKindly about 4 years

    I am using the Unity.WebApi NuGet package (Unity 4.0.1 and Unity.WebApi 5.2.3) in an ASP.NET WebApi solution. The issue I am facing is that when attempting to run the code, I get the error: Make sure that the controller has a parameterless public constructor. I've searched similar threads here, but I couldn't find any thread that matched my issue.

    Please don't just say "Add a parameterless constructor" because it shows you obviously have no clue what IoC is and why that statement makes absolutely no sense and defeats the purpose of IoC. I say this because I saw this on a lot of the other threads I've looked at thus far.

    This is my Startup.cs (I'm using Owin, so I do not have a Global.asax):

    public void Configuration(IAppBuilder app) {
        var config = new HttpConfiguration();
            config.MapHttpAttributeRoutes();
    
            // Registering unity stuff
            UnityConfig.RegisterComponents();
    
            app.UseWebApi(config);
    }
    

    This is my UnityConfig.cs:

    public static class UnityConfig {
        public static void RegisterComponents() {
            var container = new UnityContainer();
                // Register controller
                container.RegisterType<MyController>();
    
                // Register interface
                container.RegisterType<IService, Service>();
    
                GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
        }
    }
    

    This is my API Controller:

    public class MyController : ApiController {
        private IService service
    
        public MyController(IService service) {
            this.service = service;
        }
    
        public IHttpActionResult Get() {
            return Ok("All systems go!");
        }
    }
    

    EDIT

    I took the using statements out because people are having a hard time understanding that the issue occurs whether or not the using statements are there.